From 4c7e2ec92a6d97cf8821aad9baa9338133ebcefe Mon Sep 17 00:00:00 2001 From: Guillaume S Date: Mon, 25 Sep 2023 19:38:03 +0200 Subject: [PATCH 1/5] Feature/compression (#4) * Add zstd as example to compress data Update cmake * Fix cmake build Update compression process make it optional Update ReadMe * Remove zstd ref in CMakeLists.txt * Update action change checkout v4 to v4 * Update action version name Update ReadMe version name --- .github/workflows/Test_windows.yml | 4 +- CMakeLists.txt | 30 +- README.md | 30 +- cmake/Packer.cmake | 28 +- cmake/UnPacker.cmake | 18 +- libraries/zstd.hpp | 3020 ++++++++++++++++++++++++++++ sources/main.cpp | 2 +- sources/pack/Packer.cpp | 13 +- sources/unpack/UnPackFile.cpp | 17 +- 9 files changed, 3142 insertions(+), 20 deletions(-) create mode 100644 libraries/zstd.hpp diff --git a/.github/workflows/Test_windows.yml b/.github/workflows/Test_windows.yml index 752ff20..6b110c8 100644 --- a/.github/workflows/Test_windows.yml +++ b/.github/workflows/Test_windows.yml @@ -18,7 +18,7 @@ jobs: runs-on: windows-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Config executables run: | @@ -34,4 +34,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: SWPacker - path: ${{github.workspace}}\out\0.1\Release\ \ No newline at end of file + path: ${{github.workspace}}\out\1.1\Release\ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 51e2001..285e919 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/out/ ) project( "SW Packer" VERSION - 1.0 + 1.1 DESCRIPTION "Pack all resources into one file" LANGUAGES @@ -22,7 +22,7 @@ set( CMAKE_CXX_STANDARD_REQUIRED True ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/${CMAKE_PROJECT_VERSION} ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/${CMAKE_PROJECT_VERSION} ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/${CMAKE_PROJECT_VERSION} ) -set(PREFIX_MESSAGE "[${PROJECT_NAME}] ") +set( PREFIX_MESSAGE "[${PROJECT_NAME}] ") ## <=====================================> @@ -31,6 +31,30 @@ message(${PREFIX_MESSAGE} "Current cmake location: " ${CMAKE_CURRENT_SOURCE_DIR} message(${PREFIX_MESSAGE} "Project location: " ${CMAKE_SOURCE_DIR}) message(${PREFIX_MESSAGE} "Project system: " ${CMAKE_SYSTEM_NAME}) +option(SWFP_COMP "Define if the packer will enable compact process" ) + +## IMPORTED STATIC LIBRARY NAME +set( STATIC_LIB_NAME + ) + +## IMPORTED STATIC LIBRARY .lib file +set( STATIC_LIB + ) + +list(LENGTH STATIC_LIB_NAME list_len) +math(EXPR LIST_LEN "${list_len} - 1") + +if (${LIST_LEN} GREATER_EQUAL 0) + + foreach(ctr RANGE ${LIST_LEN}) + list(GET STATIC_LIB_NAME ${ctr} lib) + list(GET STATIC_LIB ${ctr} filelib) + add_library(${lib} STATIC IMPORTED) + set_target_properties(${lib} PROPERTIES + IMPORTED_LOCATION ${filelib} + ) + endforeach() +endif () include(cmake/Packer.cmake) -include(cmake/UnPacker.cmake) +include(cmake/UnPacker.cmake) \ No newline at end of file diff --git a/README.md b/README.md index bc02e1f..26d04ef 100644 --- a/README.md +++ b/README.md @@ -7,23 +7,41 @@ It builds a single file `.swfp` with all resources inside. The compilation is simple, you can choose between two target: Packer and Unpacker. ```shell mkdir "build" && cd build -cmake -G "Visual Studio 17 2022" - DCMAKE_BUILD_TYPE=[Debug/Release] .. -cmake --build . --target SWEngine-[packer/unpacker]_0.1 --config [Debug/Release] +cmake -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=[Debug/Release] .. +cmake --build . --target SWEngine-[packer/unpacker]_1.1 --config [Debug/Release] ``` +#### Option +You can define an option by using : `-D[option]=[value]` +- CMAKE_BUILD_TYPE: Debug/Release +- SWFP_COMP: ON/OFF ## Usage ### Packer Simply run the executable and give the directory you want to pack. ```shell -./SWEngine-packer_0.1 [PATH_TO_DIRECTORY] +./SWEngine-packer [PATH_TO_DIRECTORY] ``` ### UnPacker Simply run the executable and give the directory where the file `.swfp` file is. ```shell -./SWEngine-unpacker_0.1 [PATH_TO_SWFP_FILE] +./SWEngine-unpacker [PATH_TO_SWFP_FILE] ``` +### Compression +You're able to add a compression process in the packer (and decompress for unpacker). +To do so, go to `Packer.cpp` and find the `SWFP_COMP` macro and edit the code above to add +your own compression process. For `UnPacker.cpp` find `SWFP_COMP` and edit the code above. + +To enable the compression process use `-DSWFP_COMP=ON` (default: OFF). + +Note: There is a default compression algorithm: [zstd](https://github.com/facebook/zstd). \ +The header is already include in the project just build a __static__ libraries and add it to the cmake. \ +Add `zstd_static` to `STATIC_LIB_NAME` and `${CMAKE_SOURCE_DIR}/libraries/zstd_static.lib` to `STATIC_LIB` in the CMakeLists.txt. + ## Authors -The project is made by [Guillaume Soisson](https://github.com/Alvarwow69). \ -This project is based on raysan5 works for [rres](https://github.com/raysan5/rres) \ No newline at end of file +The project is made by [Guillaume Soisson](https://github.com/Alvarwow69). + +## Credits +This project is based on raysan5 works for [rres](https://github.com/raysan5/rres) \ +This project use [zstd](https://github.com/facebook/zstd) to provide default compression process. \ No newline at end of file diff --git a/cmake/Packer.cmake b/cmake/Packer.cmake index c5eeaf4..2b4e51b 100644 --- a/cmake/Packer.cmake +++ b/cmake/Packer.cmake @@ -1,5 +1,6 @@ ## PROJECT VAR ## <=====================================> +unset(EXEC) set( EXEC "SWEngine-packer_${CMAKE_PROJECT_VERSION}" ) set( EXT cpp ) ## <=====================================> @@ -15,6 +16,8 @@ set( SRC_FOLDERS ) ## INCLUDE FOLDERS set( INC_FOLDERS + ${CMAKE_CURRENT_SOURCE_DIR}/libraries/ + ${CMAKE_CURRENT_SOURCE_DIR}/includes/ ${CMAKE_CURRENT_SOURCE_DIR}/includes/file/ ${CMAKE_CURRENT_SOURCE_DIR}/includes/pack/ @@ -39,7 +42,10 @@ add_executable(${EXEC} ${SRC}) ## <=====================================> target_compile_definitions(${EXEC} PUBLIC "SWFP_PACKER") - +if (${SWFP_COMP}) + message(${PREFIX_MESSAGE} "Compression process enabled!") + target_compile_definitions(${EXEC} PUBLIC "SWFP_COMP") +endif () ## ADD INCLUDES ## <=====================================> @@ -53,6 +59,26 @@ if(MSVC) endif() ## <=====================================> +## IMPORTED STATIC LIBRARY NAME +set( STATIC_LIB_NAME + zstd_static + ) + +## IMPORTED STATIC LIBRARY .lib file +set( STATIC_LIB + ${CMAKE_SOURCE_DIR}/libraries/zstd_static.lib + ) + +## STATIC LIBRARY LINKING +## <=====================================> +if (${STATIC_LIB_NAME}) + target_link_libraries(${EXEC} + PUBLIC + ${STATIC_LIB_NAME} + ) +endif () +## <=====================================> + if (${CMAKE_BUILD_TYPE} MATCHES Debug) set_target_properties(${EXEC} PROPERTIES DEBUG_POSTFIX "d") diff --git a/cmake/UnPacker.cmake b/cmake/UnPacker.cmake index b3973bf..4c17552 100644 --- a/cmake/UnPacker.cmake +++ b/cmake/UnPacker.cmake @@ -1,5 +1,6 @@ ## PROJECT VAR ## <=====================================> +unset(EXEC) set( EXEC "SWEngine-unpacker_${CMAKE_PROJECT_VERSION}" ) set( EXT cpp ) ## <=====================================> @@ -15,6 +16,8 @@ set( SRC_FOLDERS ) ## INCLUDE FOLDERS set( INC_FOLDERS + ${CMAKE_CURRENT_SOURCE_DIR}/libraries/ + ${CMAKE_CURRENT_SOURCE_DIR}/includes/ ${CMAKE_CURRENT_SOURCE_DIR}/includes/file/ ${CMAKE_CURRENT_SOURCE_DIR}/includes/unpack/ @@ -31,7 +34,6 @@ endforeach() file(GLOB SRC ${TMP}) ## <=====================================> - ## OUTPUT ## <=====================================> ## EXECUTABLE @@ -39,7 +41,9 @@ add_executable(${EXEC} ${SRC}) ## <=====================================> target_compile_definitions(${EXEC} PUBLIC "SWFP_UNPACKER") - +if (${SWFP_COMP}) + target_compile_definitions(${EXEC} PUBLIC "SWFP_COMP") +endif () ## ADD INCLUDES ## <=====================================> target_include_directories(${EXEC} PUBLIC ${INC_FOLDERS}) @@ -52,6 +56,16 @@ if(MSVC) endif() ## <=====================================> +## STATIC LIBRARY LINKING +## <=====================================> +if (${STATIC_LIB_NAME}) + target_link_libraries(${EXEC} + PUBLIC + ${STATIC_LIB_NAME} + ) +endif () +## <=====================================> + if (${CMAKE_BUILD_TYPE} MATCHES Debug) set_target_properties(${EXEC} PROPERTIES DEBUG_POSTFIX "d") diff --git a/libraries/zstd.hpp b/libraries/zstd.hpp new file mode 100644 index 0000000..e5c3f8b --- /dev/null +++ b/libraries/zstd.hpp @@ -0,0 +1,3020 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_H_235446 +#define ZSTD_H_235446 + +/* ====== Dependencies ======*/ +#include /* INT_MAX */ +#include /* size_t */ + + +/* ===== ZSTDLIB_API : control library symbols visibility ===== */ +#ifndef ZSTDLIB_VISIBLE + /* Backwards compatibility with old macro name */ +# ifdef ZSTDLIB_VISIBILITY +# define ZSTDLIB_VISIBLE ZSTDLIB_VISIBILITY +# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default"))) +# else +# define ZSTDLIB_VISIBLE +# endif +#endif + +#ifndef ZSTDLIB_HIDDEN +# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden"))) +# else +# define ZSTDLIB_HIDDEN +# endif +#endif + +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# 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.*/ +#else +# define ZSTDLIB_API ZSTDLIB_VISIBLE +#endif + +/* Deprecation warnings : + * Should these warnings be a problem, it is generally possible to disable them, + * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual. + * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS. + */ +#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS +# define ZSTD_DEPRECATED(message) /* disable deprecation warnings */ +#else +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define ZSTD_DEPRECATED(message) [[deprecated(message)]] +# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) +# define ZSTD_DEPRECATED(message) __attribute__((deprecated(message))) +# elif defined(__GNUC__) && (__GNUC__ >= 3) +# define ZSTD_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define ZSTD_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler") +# define ZSTD_DEPRECATED(message) +# endif +#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */ + + +/******************************************************************************* + Introduction + + zstd, short for Zstandard, is a fast lossless compression algorithm, targeting + real-time compression scenarios at zlib-level and better compression ratios. + The zstd compression library provides in-memory compression and decompression + functions. + + The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), + which is currently 22. Levels >= 20, labeled `--ultra`, should be used with + caution, as they require more memory. The library also offers negative + compression levels, which extend the range of speed vs. ratio preferences. + The lower the level, the faster the speed (at the cost of compression). + + Compression can be done in: + - a single step (described as Simple API) + - a single step, reusing a context (described as Explicit context) + - unbounded multiple steps (described as Streaming compression) + + The compression ratio achievable on small data can be highly improved using + a dictionary. Dictionary compression can be performed in: + - a single step (described as Simple dictionary API) + - a single step, reusing a dictionary (described as Bulk-processing + dictionary API) + + Advanced experimental functions can be accessed using + `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. + + Advanced experimental APIs should never be used with a dynamically-linked + library. They are not "stable"; their definitions or signatures may change in + the future. Only static linking is allowed. +*******************************************************************************/ + +/*------ Version ------*/ +#define ZSTD_VERSION_MAJOR 1 +#define ZSTD_VERSION_MINOR 5 +#define ZSTD_VERSION_RELEASE 5 +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) + +/*! ZSTD_versionNumber() : + * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */ +ZSTDLIB_API unsigned ZSTD_versionNumber(void); + +#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE +#define ZSTD_QUOTE(str) #str +#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) +#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) + +/*! ZSTD_versionString() : + * Return runtime library version, like "1.4.5". Requires v1.3.0+. */ +ZSTDLIB_API const char* ZSTD_versionString(void); + +/* ************************************* + * Default constant + ***************************************/ +#ifndef ZSTD_CLEVEL_DEFAULT +# define ZSTD_CLEVEL_DEFAULT 3 +#endif + +/* ************************************* + * Constants + ***************************************/ + +/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ +#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ +#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */ +#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 + +#define ZSTD_BLOCKSIZELOG_MAX 17 +#define ZSTD_BLOCKSIZE_MAX (1<= ZSTD_compressBound(srcSize)` guarantees that zstd will have + * enough space to successfully compress the data. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*! ZSTD_decompress() : + * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + * `dstCapacity` is an upper bound of originalSize to regenerate. + * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. + * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/*! ZSTD_getFrameContentSize() : requires v1.3.0+ + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + * @return : - decompressed size of `src` frame content, if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + * note 1 : a 0 return value means the frame is valid but "empty". + * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can rely on some implicit limit, + * as ZSTD_decompress() only needs an upper bound of decompressed size. + * (For example, data could be necessarily cut into blocks <= 16 KB). + * note 3 : decompressed size is always present when compression is completed using single-pass functions, + * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + * note 4 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure return value fits within application's authorized limits. + * Each application can set its own limits. + * note 6 : This function replaces ZSTD_getDecompressedSize() */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) +ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); + +/*! ZSTD_getDecompressedSize() : + * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). + * Both functions work the same way, but ZSTD_getDecompressedSize() blends + * "empty", "unknown" and "error" results to the same return value (0), + * while ZSTD_getFrameContentSize() gives them separate return values. + * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ +ZSTD_DEPRECATED("Replaced by ZSTD_getFrameContentSize") +ZSTDLIB_API +unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+ + * `src` should point to the start of a ZSTD frame or skippable frame. + * `srcSize` must be >= first frame size + * @return : the compressed size of the first frame starting at `src`, + * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, + * or an error code if input is invalid */ +ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); + + +/*====== Helper functions ======*/ +/* ZSTD_compressBound() : + * maximum compressed size in worst case single-pass scenario. + * When invoking `ZSTD_compress()` or any other one-pass compression function, + * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize) + * as it eliminates one potential failure scenario, + * aka not enough room in dst buffer to write the compressed frame. + * Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE . + * In which case, ZSTD_compressBound() will return an error code + * which can be tested using ZSTD_isError(). + * + * ZSTD_COMPRESSBOUND() : + * same as ZSTD_compressBound(), but as a macro. + * It can be used to produce constants, which can be useful for static allocation, + * for example to size a static array on stack. + * Will produce constant value 0 if srcSize too large. + */ +#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00LLU : 0xFF00FF00U) +#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 */ +ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ +/* ZSTD_isError() : + * Most ZSTD_* functions returning a size_t value can be tested for error, + * using ZSTD_isError(). + * @return 1 if error, 0 otherwise + */ +ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ +ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */ +ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ +ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */ + + +/*************************************** +* Explicit context +***************************************/ +/*= Compression context + * When compressing many times, + * it is recommended to allocate a context just once, + * and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Note : re-using context is just a speed / resource optimization. + * It doesn't change the compression ratio, which remains identical. + * Note 2 : In multi-threaded environments, + * use one different context per thread for parallel execution. + */ +typedef struct ZSTD_CCtx_s ZSTD_CCtx; +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */ + +/*! ZSTD_compressCCtx() : + * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. + * Important : in order to behave similarly to `ZSTD_compress()`, + * this function compresses at requested compression level, + * __ignoring any other parameter__ . + * If any advanced parameter was set using the advanced API, + * they will all be reset. Only `compressionLevel` remains. + */ +ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*= Decompression context + * When decompressing many times, + * it is recommended to allocate a context only once, + * and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Use one context per thread for parallel execution. */ +typedef struct ZSTD_DCtx_s ZSTD_DCtx; +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ + +/*! ZSTD_decompressDCtx() : + * Same as ZSTD_decompress(), + * requires an allocated ZSTD_DCtx. + * Compatible with sticky parameters. + */ +ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/********************************************* +* Advanced compression API (Requires v1.4.0+) +**********************************************/ + +/* API design : + * Parameters are pushed one by one into an existing context, + * using ZSTD_CCtx_set*() functions. + * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame. + * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` ! + * __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ . + * + * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset(). + * + * This API supersedes all other "advanced" API entry points in the experimental section. + * In the future, we expect to remove from experimental API entry points which are redundant with this API. + */ + + +/* Compression strategies, listed from fastest to strongest */ +typedef enum { ZSTD_fast=1, + ZSTD_dfast=2, + ZSTD_greedy=3, + ZSTD_lazy=4, + ZSTD_lazy2=5, + ZSTD_btlazy2=6, + ZSTD_btopt=7, + ZSTD_btultra=8, + ZSTD_btultra2=9 + /* note : new strategies _might_ be added in the future. + Only the order (from fast to strong) is guaranteed */ +} ZSTD_strategy; + +typedef enum { + + /* compression parameters + * Note: When compressing with a ZSTD_CDict these parameters are superseded + * by the parameters used to construct the ZSTD_CDict. + * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */ + ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table. + * Note that exact compression parameters are dynamically determined, + * depending on both compression level and srcSize (when known). + * Default level is ZSTD_CLEVEL_DEFAULT==3. + * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. + * Note 1 : it's possible to pass a negative compression level. + * Note 2 : setting a level does not automatically set all other compression parameters + * to default. Setting this will however eventually dynamically impact the compression + * parameters which have not been manually set. The manually set + * ones will 'stick'. */ + /* Advanced compression parameters : + * It's possible to pin down compression parameters to some specific values. + * In which case, these values are no longer dynamically selected by the compressor */ + ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2. + * This will set a memory budget for streaming decompression, + * with larger values requiring more memory + * and typically compressing more. + * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. + * Special: value 0 means "use default windowLog". + * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT + * requires explicitly allowing such size at streaming decompression stage. */ + ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. + * Resulting memory usage is (1 << (hashLog+2)). + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. + * Larger tables improve compression ratio of strategies <= dFast, + * and improve speed of strategies > dFast. + * Special: value 0 means "use default hashLog". */ + ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2. + * Resulting memory usage is (1 << (chainLog+2)). + * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. + * Larger tables result in better and slower compression. + * This parameter is useless for "fast" strategy. + * It's still useful when using "dfast" strategy, + * in which case it defines a secondary probe table. + * Special: value 0 means "use default chainLog". */ + ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2. + * More attempts result in better and slower compression. + * This parameter is useless for "fast" and "dFast" strategies. + * Special: value 0 means "use default searchLog". */ + ZSTD_c_minMatch=105, /* Minimum size of searched matches. + * Note that Zstandard can still find matches of smaller size, + * it just tweaks its search algorithm to look for this size and larger. + * Larger values increase compression and decompression speed, but decrease ratio. + * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX. + * Note that currently, for all strategies < btopt, effective minimum is 4. + * , for all strategies > fast, effective maximum is 6. + * Special: value 0 means "use default minMatchLength". */ + ZSTD_c_targetLength=106, /* Impact of this field depends on strategy. + * For strategies btopt, btultra & btultra2: + * Length of Match considered "good enough" to stop search. + * Larger values make compression stronger, and slower. + * For strategy fast: + * Distance between match sampling. + * Larger values make compression faster, and weaker. + * Special: value 0 means "use default targetLength". */ + ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition. + * The higher the value of selected strategy, the more complex it is, + * resulting in stronger and slower compression. + * Special: value 0 means "use default strategy". */ + /* LDM mode parameters */ + ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. + * This parameter is designed to improve compression ratio + * for large inputs, by finding large matches at long distance. + * It increases memory usage and window size. + * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB + * except when expressly set to a different value. + * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and + * compression strategy >= ZSTD_btopt (== compression level 16+) */ + ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. + * Larger values increase memory usage and compression ratio, + * but decrease compression speed. + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX + * default: windowlog - 7. + * Special: value 0 means "automatically determine hashlog". */ + ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher. + * Larger/too small values usually decrease compression ratio. + * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. + * Special: value 0 means "use default value" (default: 64). */ + ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution. + * Larger values improve collision resolution but decrease compression speed. + * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX. + * Special: value 0 means "use default value" (default: 3). */ + ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table. + * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). + * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. + * Larger values improve compression speed. + * Deviating far from default value will likely result in a compression ratio decrease. + * Special: value 0 means "automatically determine hashRateLog". */ + + /* frame parameters */ + ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) + * Content size must be known at the beginning of compression. + * This is automatically the case when using ZSTD_compress2(), + * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */ + ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */ + ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ + + /* multi-threading parameters */ + /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). + * Otherwise, trying to set any other value than default (0) will be a no-op and return an error. + * In a situation where it's unknown if the linked library supports multi-threading or not, + * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property. + */ + ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. + * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() : + * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, + * while compression is performed in parallel, within worker thread(s). + * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : + * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). + * More workers improve speed, but also increase memory usage. + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, + * compression is performed inside Caller's thread, and all invocations are blocking */ + ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. + * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. + * 0 means default, which is dynamically determined based on compression parameters. + * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest. + * The minimum size is automatically and transparently enforced. */ + ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. + * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. + * It helps preserve compression ratio, while each job is compressed in parallel. + * This value is enforced only when nbWorkers >= 1. + * Larger values increase compression ratio, but decrease speed. + * Possible values range from 0 to 9 : + * - 0 means "default" : value will be determined by the library, depending on strategy + * - 1 means "no overlap" + * - 9 means "full overlap", using a full window size. + * Each intermediate rank increases/decreases load size by a factor 2 : + * 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 + * default value varies between 6 and 9, depending on strategy */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_c_rsyncable + * ZSTD_c_format + * ZSTD_c_forceMaxWindow + * ZSTD_c_forceAttachDict + * ZSTD_c_literalCompressionMode + * ZSTD_c_targetCBlockSize + * ZSTD_c_srcSizeHint + * ZSTD_c_enableDedicatedDictSearch + * ZSTD_c_stableInBuffer + * ZSTD_c_stableOutBuffer + * ZSTD_c_blockDelimiters + * ZSTD_c_validateSequences + * ZSTD_c_useBlockSplitter + * ZSTD_c_useRowMatchFinder + * ZSTD_c_prefetchCDictTables + * ZSTD_c_enableSeqProducerFallback + * ZSTD_c_maxBlockSize + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly; + * also, the enums values themselves are unstable and can still change. + */ + ZSTD_c_experimentalParam1=500, + ZSTD_c_experimentalParam2=10, + ZSTD_c_experimentalParam3=1000, + ZSTD_c_experimentalParam4=1001, + ZSTD_c_experimentalParam5=1002, + ZSTD_c_experimentalParam6=1003, + ZSTD_c_experimentalParam7=1004, + ZSTD_c_experimentalParam8=1005, + ZSTD_c_experimentalParam9=1006, + ZSTD_c_experimentalParam10=1007, + ZSTD_c_experimentalParam11=1008, + ZSTD_c_experimentalParam12=1009, + ZSTD_c_experimentalParam13=1010, + ZSTD_c_experimentalParam14=1011, + ZSTD_c_experimentalParam15=1012, + ZSTD_c_experimentalParam16=1013, + ZSTD_c_experimentalParam17=1014, + ZSTD_c_experimentalParam18=1015, + ZSTD_c_experimentalParam19=1016 +} ZSTD_cParameter; + +typedef struct { + size_t error; + int lowerBound; + int upperBound; +} ZSTD_bounds; + +/*! ZSTD_cParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - lower and upper bounds, both inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam); + +/*! ZSTD_CCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_cParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is generally only possible during frame initialization (before starting compression). + * Exception : when using multi-threading mode (nbWorkers >= 1), + * the following parameters can be updated _during_ compression (within same frame): + * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. + * new parameters will be active for next job only (after a flush()). + * @return : an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtx_setPledgedSrcSize() : + * Total input data size to be compressed as a single frame. + * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag. + * This value will also be controlled at end of frame, and trigger an error if not respected. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame. + * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. + * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame. + * Note 2 : pledgedSrcSize is only valid once, for the next frame. + * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN. + * Note 3 : Whenever all input data is provided and consumed in a single round, + * for example with ZSTD_compress2(), + * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), + * this value is automatically overridden by srcSize instead. + */ +ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); + +typedef enum { + ZSTD_reset_session_only = 1, + ZSTD_reset_parameters = 2, + ZSTD_reset_session_and_parameters = 3 +} ZSTD_ResetDirective; + +/*! ZSTD_CCtx_reset() : + * There are 2 different things that can be reset, independently or jointly : + * - The session : will stop compressing current frame, and make CCtx ready to start a new one. + * Useful after an error, or to interrupt any ongoing compression. + * Any internal data not yet flushed is cancelled. + * Compression parameters and dictionary remain unchanged. + * They will be used to compress next frame. + * Resetting session never fails. + * - The parameters : changes all parameters back to "default". + * This also removes any reference to any dictionary or external sequence producer. + * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing) + * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError()) + * - Both : similar to resetting the session, followed by resetting parameters. + */ +ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); + +/*! ZSTD_compress2() : + * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API. + * ZSTD_compress2() always starts a new frame. + * Should cctx hold data from a previously unfinished frame, everything about it is forgotten. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - The function is always blocking, returns when compression is completed. + * NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have + * enough space to successfully compress the data, though it is possible it fails for other reasons. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/*********************************************** +* Advanced decompression API (Requires v1.4.0+) +************************************************/ + +/* The advanced API pushes parameters one by one into an existing DCtx context. + * Parameters are sticky, and remain valid for all following frames + * using the same DCtx context. + * It's possible to reset parameters to default values using ZSTD_DCtx_reset(). + * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream(). + * Therefore, no new decompression function is necessary. + */ + +typedef enum { + + ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which + * the streaming API will refuse to allocate memory buffer + * in order to protect the host from unreasonable memory requirements. + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT). + * Special: value 0 means "use default maximum windowLog". */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_d_format + * ZSTD_d_stableOutBuffer + * ZSTD_d_forceIgnoreChecksum + * ZSTD_d_refMultipleDDicts + * ZSTD_d_disableHuffmanAssembly + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly + */ + ZSTD_d_experimentalParam1=1000, + ZSTD_d_experimentalParam2=1001, + ZSTD_d_experimentalParam3=1002, + ZSTD_d_experimentalParam4=1003, + ZSTD_d_experimentalParam5=1004 + +} ZSTD_dParameter; + +/*! ZSTD_dParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - both lower and upper bounds, inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam); + +/*! ZSTD_DCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_dParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is only possible during frame initialization (before starting decompression). + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value); + +/*! ZSTD_DCtx_reset() : + * Return a DCtx to clean state. + * Session and parameters can be reset jointly or separately. + * Parameters can only be reset when no active frame is being decompressed. + * @return : 0, or an error code, which can be tested with ZSTD_isError() + */ +ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); + + +/**************************** +* Streaming +****************************/ + +typedef struct ZSTD_inBuffer_s { + const void* src; /**< start of input buffer */ + size_t size; /**< size of input buffer */ + size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_inBuffer; + +typedef struct ZSTD_outBuffer_s { + void* dst; /**< start of output buffer */ + size_t size; /**< size of output buffer */ + size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_outBuffer; + + + +/*-*********************************************************************** +* Streaming compression - HowTo +* +* A ZSTD_CStream object is required to track streaming operation. +* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. +* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. +* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory. +* +* For parallel execution, use one separate ZSTD_CStream per thread. +* +* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing. +* +* Parameters are sticky : when starting a new compression on the same context, +* it will re-use the same sticky parameters as previous compression session. +* When in doubt, it's recommended to fully initialize the context before usage. +* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(), +* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to +* set more specific parameters, the pledged source size, or load a dictionary. +* +* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to +* consume input stream. The function will automatically update both `pos` +* fields within `input` and `output`. +* Note that the function may not consume the entire input, for example, because +* the output buffer is already full, in which case `input.pos < input.size`. +* The caller must check if input has been entirely consumed. +* If not, the caller must make some room to receive more compressed data, +* and then present again remaining input data. +* note: ZSTD_e_continue is guaranteed to make some forward progress when called, +* but doesn't guarantee maximal forward progress. This is especially relevant +* when compressing with multiple threads. The call won't block if it can +* consume some input, but if it can't it will wait for some, but not all, +* output to be flushed. +* @return : provides a minimum amount of data remaining to be flushed from internal buffers +* or an error code, which can be tested using ZSTD_isError(). +* +* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, +* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated. +* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0). +* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the +* operation. +* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if internal buffers are entirely flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* The epilogue is required for decoders to consider a frame completed. +* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to +* start a new frame. +* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if frame fully completed and fully flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* *******************************************************************/ + +typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ + /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ +/*===== ZSTD_CStream management functions =====*/ +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */ + +/*===== Streaming compression functions =====*/ +typedef enum { + ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ + ZSTD_e_flush=1, /* flush any data provided so far, + * it creates (at least) one new block, that can be decoded immediately on reception; + * frame will continue: any future data can still reference previously compressed data, improving compression. + * note : multithreaded compression will block to flush as much output as possible. */ + ZSTD_e_end=2 /* flush any remaining data _and_ close current frame. + * note that frame is only closed after compressed data is fully flushed (return value == 0). + * After that point, any additional data starts a new frame. + * note : each frame is independent (does not reference any content from previous frame). + : note : multithreaded compression will block to flush as much output as possible. */ +} ZSTD_EndDirective; + +/*! ZSTD_compressStream2() : Requires v1.4.0+ + * Behaves about the same as ZSTD_compressStream, with additional control on end directive. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) + * - output->pos must be <= dstCapacity, input->pos must be <= srcSize + * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - endOp must be a valid directive + * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. + * - 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, + * and then immediately returns, just indicating that there is some data remaining to be flushed. + * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. + * - 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. + * - @return provides a minimum amount of data remaining to be flushed from internal buffers + * or an error code, which can be tested using ZSTD_isError(). + * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. + * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. + * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. + * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), + * only ZSTD_e_end or ZSTD_e_flush operations are allowed. + * Before starting a new compression job, or changing compression parameters, + * it is required to fully flush internal buffers. + */ +ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); + + +/* These buffer sizes are softly recommended. + * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. + * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), + * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. + * + * However, note that these recommendations are from the perspective of a C caller program. + * If the streaming interface is invoked from some other language, + * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, + * a major performance rule is to reduce crossing such interface to an absolute minimum. + * It's not rare that performance ends being spent more into the interface, rather than compression itself. + * In which cases, prefer using large buffers, as large as practical, + * for both input and output, to reduce the nb of roundtrips. + */ +ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ + + +/* ***************************************************************************** + * This following is a legacy streaming API, available since v1.0+ . + * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). + * It is redundant, but remains fully supported. + ******************************************************************************/ + +/*! + * Equivalent to: + * + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * + * Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API + * to compress with a dictionary. + */ +ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); +/*! + * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). + * NOTE: The return value is different. ZSTD_compressStream() returns a hint for + * the next read size (if non-zero and not an error). ZSTD_compressStream2() + * returns the minimum nb of bytes left to flush (if non-zero and not an error). + */ +ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ +ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ +ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); + + +/*-*************************************************************************** +* Streaming decompression - HowTo +* +* A ZSTD_DStream object is required to track streaming operations. +* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. +* ZSTD_DStream objects can be re-used multiple times. +* +* Use ZSTD_initDStream() to start a new decompression operation. +* @return : recommended first input size +* Alternatively, use advanced API to set specific properties. +* +* Use ZSTD_decompressStream() repetitively to consume your input. +* The function will update both `pos` fields. +* If `input.pos < input.size`, some input has not been consumed. +* It's up to the caller to present again remaining data. +* The function tries to flush all data decoded immediately, respecting output buffer size. +* If `output.pos < output.size`, decoder has flushed everything it could. +* But if `output.pos == output.size`, there might be some data left within internal buffers., +* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. +* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. +* @return : 0 when a frame is completely decoded and fully flushed, +* or an error code, which can be tested using ZSTD_isError(), +* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : +* the return value is a suggested next input size (just a hint for better latency) +* that will never request more than the remaining frame size. +* *******************************************************************************/ + +typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ + /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ +/*===== ZSTD_DStream management functions =====*/ +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */ + +/*===== Streaming decompression functions =====*/ + +/*! ZSTD_initDStream() : + * Initialize/reset DStream state for new decompression operation. + * Call before new decompression operation using same DStream. + * + * Note : This function is redundant with the advanced API and equivalent to: + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, NULL); + */ +ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); + +/*! ZSTD_decompressStream() : + * Streaming decompression function. + * Call repetitively to consume full input updating it as necessary. + * Function will update both input and output `pos` fields exposing current state via these fields: + * - `input.pos < input.size`, some input remaining and caller should provide remaining input + * on the next call. + * - `output.pos < output.size`, decoder finished and flushed all remaining buffers. + * - `output.pos == output.size`, potentially uncflushed data present in the internal buffers, + * call ZSTD_decompressStream() again to flush remaining data to output. + * Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX. + * + * @return : 0 when a frame is completely decoded and fully flushed, + * or an error code, which can be tested using ZSTD_isError(), + * or any other value > 0, which means there is some decoding or flushing to do to complete current frame. + */ +ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); + +ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ + + +/************************** +* Simple dictionary API +***************************/ +/*! ZSTD_compress_usingDict() : + * Compression at an explicit compression level using a Dictionary. + * A dictionary can be any arbitrary data segment (also called a prefix), + * or a buffer with specified information (see zdict.h). + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + int compressionLevel); + +/*! ZSTD_decompress_usingDict() : + * Decompression using a known Dictionary. + * Dictionary must be identical to the one used during compression. + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/*********************************** + * Bulk processing dictionary API + **********************************/ +typedef struct ZSTD_CDict_s ZSTD_CDict; + +/*! ZSTD_createCDict() : + * When compressing multiple messages or blocks using the same dictionary, + * it's recommended to digest the dictionary only once, since it's a costly operation. + * ZSTD_createCDict() will create a state from digesting a dictionary. + * The resulting state can be used for future compression operations with very limited startup cost. + * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. + * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict. + * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content. + * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer, + * in which case the only thing that it transports is the @compressionLevel. + * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, + * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, + int compressionLevel); + +/*! ZSTD_freeCDict() : + * Function frees memory allocated by ZSTD_createCDict(). + * If a NULL pointer is passed, no operation is performed. */ +ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); + +/*! ZSTD_compress_usingCDict() : + * Compression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. + * Note : compression level is _decided at dictionary creation time_, + * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict); + + +typedef struct ZSTD_DDict_s ZSTD_DDict; + +/*! ZSTD_createDDict() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_freeDDict() : + * Function frees memory allocated with ZSTD_createDDict() + * If a NULL pointer is passed, no operation is performed. */ +ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); + +/*! ZSTD_decompress_usingDDict() : + * Decompression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_DDict* ddict); + + +/******************************** + * Dictionary helper functions + *******************************/ + +/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+ + * Provides the dictID stored within dictionary. + * if @return == 0, the dictionary is not conformant with Zstandard specification. + * It can still be loaded, but as a content-only dictionary. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); + +/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+ + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict); + +/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+ + * Provides the dictID of the dictionary loaded into `ddict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); + +/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+ + * Provides the dictID required to decompressed the frame stored within `src`. + * If @return == 0, the dictID could not be decoded. + * This could for one of the following reasons : + * - The frame does not require a dictionary to be decoded (most common case). + * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden piece of information. + * Note : this use case also happens when using a non-conformant dictionary. + * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). + * - This is not a Zstandard frame. + * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); + + +/******************************************************************************* + * Advanced dictionary and prefix API (Requires v1.4.0+) + * + * This API allows dictionaries to be used with ZSTD_compress2(), + * ZSTD_compressStream2(), and ZSTD_decompressDCtx(). + * Dictionaries are sticky, they remain valid when same context is re-used, + * they only reset when the context is reset + * with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters. + * In contrast, Prefixes are single-use. + ******************************************************************************/ + + +/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+ + * Create an internal CDict from `dict` buffer. + * Decompression will have to use same dictionary. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Dictionary is sticky, it will be used for all future compressed frames, + * until parameters are reset, a new dictionary is loaded, or the dictionary + * is explicitly invalidated by loading a NULL dictionary. + * Note 2 : Loading a dictionary involves building tables. + * It's also a CPU consuming operation, with non-negligible impact on latency. + * Tables are dependent on compression parameters, and for this reason, + * compression parameters can no longer be changed after loading a dictionary. + * Note 3 :`dict` content will be copied internally. + * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead. + * In such a case, dictionary buffer must outlive its users. + * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() + * to precisely select how dictionary content must be interpreted. + * Note 5 : This method does not benefit from LDM (long distance mode). + * If you want to employ LDM on some large dictionary content, + * prefer employing ZSTD_CCtx_refPrefix() described below. + */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+ + * Reference a prepared dictionary, to be used for all future compressed frames. + * Note that compression parameters are enforced from within CDict, + * and supersede any compression parameter previously set within CCtx. + * The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. + * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. + * The dictionary will remain valid for future compressed frames using same CCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Referencing a NULL CDict means "return to no-dictionary mode". + * Note 1 : Currently, only one dictionary can be managed. + * Referencing a new dictionary effectively "discards" any previous one. + * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ +ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); + +/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+ + * Reference a prefix (single-usage dictionary) for next compressed frame. + * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). + * Decompression will need same prefix to properly regenerate data. + * Compressing with a prefix is similar in outcome as performing a diff and compressing it, + * but performs much faster, especially during decompression (compression speed is tunable with compression level). + * This method is compatible with LDM (long distance mode). + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary + * Note 1 : Prefix buffer is referenced. It **must** outlive compression. + * Its content must remain unmodified during compression. + * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, + * ensure that the window size is large enough to contain the entire source. + * See ZSTD_c_windowLog. + * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. + * It's a CPU consuming operation, with non-negligible impact on latency. + * If there is a need to use the same prefix multiple times, consider loadDictionary instead. + * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). + * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, + const void* prefix, size_t prefixSize); + +/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+ + * Create an internal DDict from dict buffer, to be used to decompress all future frames. + * The dictionary remains valid for all future frames, until explicitly invalidated, or + * a new dictionary is loaded. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Loading a dictionary involves building tables, + * which has a non-negligible impact on CPU usage and latency. + * It's recommended to "load once, use many times", to amortize the cost + * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading. + * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead. + * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of + * how dictionary content is loaded and interpreted. + */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+ + * Reference a prepared dictionary, to be used to decompress next frames. + * The dictionary remains active for decompression of future frames using same DCtx. + * + * If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function + * will store the DDict references in a table, and the DDict used for decompression + * will be determined at decompression time, as per the dict ID in the frame. + * The memory for the table is allocated on the first call to refDDict, and can be + * freed with ZSTD_freeDCtx(). + * + * If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary + * will be managed, and referencing a dictionary effectively "discards" any previous one. + * + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: referencing a NULL DDict means "return to no-dictionary mode". + * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+ + * Reference a prefix (single-usage dictionary) to decompress next frame. + * This is the reverse operation of ZSTD_CCtx_refPrefix(), + * and must use the same prefix as the one used during compression. + * Prefix is **only used once**. Reference is discarded at end of frame. + * End of frame is reached when ZSTD_decompressStream() returns 0. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary + * Note 2 : Prefix buffer is referenced. It **must** outlive decompression. + * Prefix buffer must remain unmodified up to the end of frame, + * reached when ZSTD_decompressStream() returns 0. + * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent). + * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section) + * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. + * A full dictionary is more costly, as it requires building tables. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, + const void* prefix, size_t prefixSize); + +/* === Memory management === */ + +/*! ZSTD_sizeof_*() : Requires v1.4.0+ + * These functions give the _current_ memory usage of selected object. + * Note that object memory usage can evolve (increase or decrease) over time. */ +ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); + +#endif /* ZSTD_H_235446 */ + + +/* ************************************************************************************** + * ADVANCED AND EXPERIMENTAL FUNCTIONS + **************************************************************************************** + * The definitions in the following section are considered experimental. + * They are provided for advanced scenarios. + * They should never be used with a dynamic library, as prototypes may change in the future. + * Use them only in association with static linking. + * ***************************************************************************************/ + +#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) +#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY + +/* This can be overridden externally to hide static symbols. */ +#ifndef ZSTDLIB_STATIC_API +# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE +# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE +# else +# define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE +# endif +#endif + +/**************************************************************************************** + * experimental API (static linking only) + **************************************************************************************** + * The following symbols and constants + * are not planned to join "stable API" status in the near future. + * They can still change in future versions. + * Some of them are planned to remain in the static_only section indefinitely. + * Some of them might be removed in the future (especially when redundant with existing stable functions) + * ***************************************************************************************/ + +#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */ +#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2) +#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */ +#define ZSTD_SKIPPABLEHEADERSIZE 8 + +/* compression parameter bounds */ +#define ZSTD_WINDOWLOG_MAX_32 30 +#define ZSTD_WINDOWLOG_MAX_64 31 +#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) +#define ZSTD_WINDOWLOG_MIN 10 +#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) +#define ZSTD_HASHLOG_MIN 6 +#define ZSTD_CHAINLOG_MAX_32 29 +#define ZSTD_CHAINLOG_MAX_64 30 +#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) +#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN +#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) +#define ZSTD_SEARCHLOG_MIN 1 +#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ +#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */ +#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX +#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ +#define ZSTD_STRATEGY_MIN ZSTD_fast +#define ZSTD_STRATEGY_MAX ZSTD_btultra2 +#define ZSTD_BLOCKSIZE_MAX_MIN (1 << 10) /* The minimum valid max blocksize. Maximum blocksizes smaller than this make compressBound() inaccurate. */ + + +#define ZSTD_OVERLAPLOG_MIN 0 +#define ZSTD_OVERLAPLOG_MAX 9 + +#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame + * requiring larger than (1< 0: + * If litLength != 0: + * rep == 1 --> offset == repeat_offset_1 + * rep == 2 --> offset == repeat_offset_2 + * rep == 3 --> offset == repeat_offset_3 + * If litLength == 0: + * rep == 1 --> offset == repeat_offset_2 + * rep == 2 --> offset == repeat_offset_3 + * rep == 3 --> offset == repeat_offset_1 - 1 + * + * Note: This field is optional. ZSTD_generateSequences() will calculate the value of + * 'rep', but repeat offsets do not necessarily need to be calculated from an external + * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * use this 'rep' field at all (as of now). + */ +} ZSTD_Sequence; + +typedef struct { + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ + unsigned hashLog; /**< dispatch table : larger == faster, more memory */ + unsigned searchLog; /**< nb of searches : larger == more compression, slower */ + unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ + unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ + ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ +} ZSTD_compressionParameters; + +typedef struct { + int contentSizeFlag; /**< 1: content size will be in frame header (when known) */ + int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */ + int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */ +} ZSTD_frameParameters; + +typedef struct { + ZSTD_compressionParameters cParams; + ZSTD_frameParameters fParams; +} ZSTD_parameters; + +typedef enum { + ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ + ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ + ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ +} ZSTD_dictContentType_e; + +typedef enum { + ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ + ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ +} ZSTD_dictLoadMethod_e; + +typedef enum { + ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ + ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. + * Useful to save 4 bytes per generated frame. + * Decoder cannot recognise automatically this format, requiring this instruction. */ +} ZSTD_format_e; + +typedef enum { + /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */ + ZSTD_d_validateChecksum = 0, + ZSTD_d_ignoreChecksum = 1 +} ZSTD_forceIgnoreChecksum_e; + +typedef enum { + /* Note: this enum controls ZSTD_d_refMultipleDDicts */ + ZSTD_rmd_refSingleDDict = 0, + ZSTD_rmd_refMultipleDDicts = 1 +} ZSTD_refMultipleDDicts_e; + +typedef enum { + /* Note: this enum and the behavior it controls are effectively internal + * implementation details of the compressor. They are expected to continue + * to evolve and should be considered only in the context of extremely + * advanced performance tuning. + * + * Zstd currently supports the use of a CDict in three ways: + * + * - The contents of the CDict can be copied into the working context. This + * means that the compression can search both the dictionary and input + * while operating on a single set of internal tables. This makes + * the compression faster per-byte of input. However, the initial copy of + * the CDict's tables incurs a fixed cost at the beginning of the + * compression. For small compressions (< 8 KB), that copy can dominate + * the cost of the compression. + * + * - The CDict's tables can be used in-place. In this model, compression is + * slower per input byte, because the compressor has to search two sets of + * tables. However, this model incurs no start-up cost (as long as the + * working context's tables can be reused). For small inputs, this can be + * faster than copying the CDict's tables. + * + * - The CDict's tables are not used at all, and instead we use the working + * context alone to reload the dictionary and use params based on the source + * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). + * This method is effective when the dictionary sizes are very small relative + * to the input size, and the input size is fairly large to begin with. + * + * Zstd has a simple internal heuristic that selects which strategy to use + * at the beginning of a compression. However, if experimentation shows that + * Zstd is making poor choices, it is possible to override that choice with + * this enum. + */ + ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ + ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ + ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ + ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ +} ZSTD_dictAttachPref_e; + +typedef enum { + ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. + * Negative compression levels will be uncompressed, and positive compression + * levels will be compressed. */ + ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be + * emitted if Huffman compression is not profitable. */ + ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ +} ZSTD_literalCompressionMode_e; + +typedef enum { + /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final + * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable + * or ZSTD_ps_disable allow for a force enable/disable the feature. + */ + ZSTD_ps_auto = 0, /* Let the library automatically determine whether the feature shall be enabled */ + ZSTD_ps_enable = 1, /* Force-enable the feature */ + ZSTD_ps_disable = 2 /* Do not use the feature */ +} ZSTD_paramSwitch_e; + +/*************************************** +* Frame header and size functions +***************************************/ + +/*! ZSTD_findDecompressedSize() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - decompressed size of all data in all successive frames + * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * note 2 : decompressed size is always present when compression is done with ZSTD_compress() + * note 3 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure result fits within application's authorized limits. + * Each application can set its own limits. + * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + * read each contained frame header. This is fast as most of the data is skipped, + * however it does mean that all frame data must be present and valid. */ +ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_decompressBound() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - upper-bound for the decompressed size of all data in all successive frames + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. + * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. + * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value. + * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: + * upper-bound = # blocks * min(128 KB, Window_Size) + */ +ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); + +/*! ZSTD_frameHeaderSize() : + * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. + * @return : size of the Frame Header, + * or an error code (if srcSize is too small) */ +ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); + +typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; +typedef struct { + unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ + unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ + unsigned blockSizeMax; + ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ + unsigned headerSize; + unsigned dictID; + unsigned checksumFlag; + unsigned _reserved1; + unsigned _reserved2; +} ZSTD_frameHeader; + +/*! ZSTD_getFrameHeader() : + * decode Frame Header, or requires larger `srcSize`. + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +/*! ZSTD_getFrameHeader_advanced() : + * same as ZSTD_getFrameHeader(), + * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); + +/*! ZSTD_decompressionMargin() : + * Zstd supports in-place decompression, where the input and output buffers overlap. + * In this case, the output buffer must be at least (Margin + Output_Size) bytes large, + * and the input buffer must be at the end of the output buffer. + * + * _______________________ Output Buffer ________________________ + * | | + * | ____ Input Buffer ____| + * | | | + * v v v + * |---------------------------------------|-----------|----------| + * ^ ^ ^ + * |___________________ Output_Size ___________________|_ Margin _| + * + * NOTE: See also ZSTD_DECOMPRESSION_MARGIN(). + * NOTE: This applies only to single-pass decompression through ZSTD_decompress() or + * ZSTD_decompressDCtx(). + * NOTE: This function supports multi-frame input. + * + * @param src The compressed frame(s) + * @param srcSize The size of the compressed frame(s) + * @returns The decompression margin or an error that can be checked with ZSTD_isError(). + */ +ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize); + +/*! ZSTD_DECOMPRESS_MARGIN() : + * Similar to ZSTD_decompressionMargin(), but instead of computing the margin from + * the compressed frame, compute it from the original size and the blockSizeLog. + * See ZSTD_decompressionMargin() for details. + * + * WARNING: This macro does not support multi-frame input, the input must be a single + * zstd frame. If you need that support use the function, or implement it yourself. + * + * @param originalSize The original uncompressed size of the data. + * @param blockSize The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX). + * Unless you explicitly set the windowLog smaller than + * ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX. + */ +#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)( \ + ZSTD_FRAMEHEADERSIZE_MAX /* Frame header */ + \ + 4 /* checksum */ + \ + ((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) /* 3 bytes per block */ + \ + (blockSize) /* One block of margin */ \ + )) + +typedef enum { + ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */ + ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */ +} ZSTD_sequenceFormat_e; + +/*! ZSTD_sequenceBound() : + * `srcSize` : size of the input buffer + * @return : upper-bound for the number of sequences that can be generated + * from a buffer of srcSize bytes + * + * note : returns number of sequences - to get bytes, multiply by sizeof(ZSTD_Sequence). + */ +ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize); + +/*! ZSTD_generateSequences() : + * Generate sequences using ZSTD_compress2(), given a source buffer. + * + * Each block will end with a dummy sequence + * with offset == 0, matchLength == 0, and litLength == length of last literals. + * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0) + * simply acts as a block delimiter. + * + * @zc can be used to insert custom compression params. + * This function invokes ZSTD_compress2(). + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters + * @return : number of sequences generated + */ + +ZSTDLIB_STATIC_API size_t +ZSTD_generateSequences( ZSTD_CCtx* zc, + ZSTD_Sequence* outSeqs, size_t outSeqsSize, + const void* src, size_t srcSize); + +/*! ZSTD_mergeBlockDelimiters() : + * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals + * by merging them into the literals of the next sequence. + * + * As such, the final generated result has no explicit representation of block boundaries, + * and the final last literals segment is not represented in the sequences. + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters + * @return : number of sequences left after merging + */ +ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize); + +/*! ZSTD_compressSequences() : + * Compress an array of ZSTD_Sequence, associated with @src buffer, into dst. + * @src contains the entire input (not just the literals). + * If @srcSize > sum(sequence.length), the remaining bytes are considered all literals + * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + * The entire source is compressed into a single frame. + * + * The compression behavior changes based on cctx params. In particular: + * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on + * the block size derived from the cctx, and sequences may be split. This is the default setting. + * + * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + * + * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined + * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + * + * In addition to the two adjustable experimental params, there are other important cctx params. + * - 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. + * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression. + * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset + * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md + * + * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. + * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, + * and cannot emit an RLE block that disagrees with the repcode history + * @return : final compressed size, or a ZSTD error code. + */ +ZSTDLIB_STATIC_API size_t +ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize); + + +/*! ZSTD_writeSkippableFrame() : + * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer. + * + * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number, + * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15. + * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so + * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant. + * + * Returns an error if destination buffer is not large enough, if the source size is not representable + * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid). + * + * @return : number of bytes written or a ZSTD error. + */ +ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, unsigned magicVariant); + +/*! ZSTD_readSkippableFrame() : + * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer. + * + * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written, + * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested + * in the magicVariant. + * + * Returns an error if destination buffer is not large enough, or if the frame is not skippable. + * + * @return : number of bytes written or a ZSTD error. + */ +ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant, + const void* src, size_t srcSize); + +/*! ZSTD_isSkippableFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame. + */ +ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size); + + + +/*************************************** +* Memory management +***************************************/ + +/*! ZSTD_estimate*() : + * These functions make it possible to estimate memory usage + * of a future {D,C}Ctx, before its creation. + * + * ZSTD_estimateCCtxSize() will provide a memory budget large enough + * for any compression level up to selected one. + * Note : Unlike ZSTD_estimateCStreamSize*(), this estimate + * does not include space for a window buffer. + * Therefore, the estimation is only guaranteed for single-shot compressions, not streaming. + * The estimate will assume the input may be arbitrarily large, + * which is the worst case. + * + * When srcSize can be bound by a known and rather "small" value, + * this fact can be used to provide a tighter estimation + * because the CCtx compression context will need less memory. + * This tighter estimation can be provided by more advanced functions + * ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(), + * and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter(). + * Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits. + * + * Note : only single-threaded compression is supported. + * ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. + * + * Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the Block-Level Sequence Producer API at this time. + * Size estimates assume that no external sequence producer is registered. + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void); + +/*! ZSTD_estimateCStreamSize() : + * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one. + * It will also consider src size to be arbitrarily "large", which is worst case. + * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. + * 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. + * Note : CStream size estimation is only correct for single-threaded compression. + * ZSTD_DStream memory budget depends on window Size. + * This information can be passed manually, using ZSTD_estimateDStreamSize, + * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); + * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + * an internal ?Dict will be created, which additional size is not estimated here. + * In this case, get total size by adding ZSTD_estimate?DictSize + * Note 2 : only single-threaded compression is supported. + * ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. + * Note 3 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time. + * Size estimates assume that no external sequence producer is registered. + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t windowSize); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); + +/*! ZSTD_estimate?DictSize() : + * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). + * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). + * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); + +/*! ZSTD_initStatic*() : + * Initialize an object using a pre-allocated fixed-size buffer. + * workspace: The memory area to emplace the object into. + * Provided pointer *must be 8-bytes aligned*. + * Buffer must outlive object. + * workspaceSize: Use ZSTD_estimate*Size() to determine + * how large workspace must be to support target scenario. + * @return : pointer to object (same address as workspace, just different type), + * or NULL if error (size too small, incorrect alignment, etc.) + * Note : zstd will never resize nor malloc() when using a static buffer. + * If the object requires more memory than available, + * zstd will just error out (typically ZSTD_error_memory_allocation). + * Note 2 : there is no corresponding "free" function. + * Since workspace is allocated externally, it must be freed externally too. + * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level + * into its associated cParams. + * Limitation 1 : currently not compatible with internal dictionary creation, triggered by + * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). + * Limitation 2 : static cctx currently not compatible with multi-threading. + * Limitation 3 : static dctx is incompatible with legacy support. + */ +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ + +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ + +ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams); + +ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType); + + +/*! Custom memory allocation : + * These prototypes make it possible to pass your own allocation/free functions. + * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. + * All allocation/free operations will be completed using these custom variants instead of regular ones. + */ +typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); +typedef void (*ZSTD_freeFunction) (void* opaque, void* address); +typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; +static +#ifdef __GNUC__ +__attribute__((__unused__)) +#endif +ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ + +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); + +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem); + +/*! Thread pool : + * These prototypes make it possible to share a thread pool among multiple compression contexts. + * This can limit resources for applications with multiple threads where each one uses + * a threaded compression mode (via ZSTD_c_nbWorkers parameter). + * ZSTD_createThreadPool creates a new thread pool with a given number of threads. + * Note that the lifetime of such pool must exist while being used. + * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value + * to use an internal thread pool). + * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer. + */ +typedef struct POOL_ctx_s ZSTD_threadPool; +ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads); +ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool); + + +/* + * This API is temporary and is expected to change or disappear in the future! + */ +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* cctxParams, + ZSTD_customMem customMem); + +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem); + + +/*************************************** +* Advanced compression functions +***************************************/ + +/*! ZSTD_createCDict_byReference() : + * Create a digested dictionary for compression + * Dictionary content is just referenced, not duplicated. + * As a consequence, `dictBuffer` **must** outlive CDict, + * and its content must remain unmodified throughout the lifetime of CDict. + * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); + +/*! ZSTD_getCParams() : + * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. + * `estimatedSrcSize` value is optional, select 0 if not known */ +ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_getParams() : + * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. + * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ +ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_checkCParams() : + * Ensure param values remain within authorized range. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */ +ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); + +/*! ZSTD_adjustCParams() : + * optimize params for a given `srcSize` and `dictSize`. + * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN. + * `dictSize` must be `0` when there is no dictionary. + * cPar can be invalid : all parameters will be clamped within valid range in the @return struct. + * This function never fails (wide contract) */ +ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); + +/*! ZSTD_CCtx_setCParams() : + * Set all parameters provided within @p cparams into the working @p cctx. + * Note : if modifying parameters during compression (MT mode only), + * note that changes to the .windowLog parameter will be ignored. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + * On failure, no parameters are updated. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams); + +/*! ZSTD_CCtx_setFParams() : + * Set all parameters provided within @p fparams into the working @p cctx. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams); + +/*! ZSTD_CCtx_setParams() : + * Set all parameters provided within @p params into the working @p cctx. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params); + +/*! ZSTD_compress_advanced() : + * Note : this function is now DEPRECATED. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2") +ZSTDLIB_STATIC_API +size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + ZSTD_parameters params); + +/*! ZSTD_compress_usingCDict_advanced() : + * Note : this function is now DEPRECATED. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary") +ZSTDLIB_STATIC_API +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams); + + +/*! ZSTD_CCtx_loadDictionary_byReference() : + * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. + * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_loadDictionary_advanced() : + * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ +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); + +/*! ZSTD_CCtx_refPrefix_advanced() : + * Same as ZSTD_CCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/* === experimental parameters === */ +/* these parameters can be used with ZSTD_setParameter() + * they are not guaranteed to remain supported in the future */ + + /* Enables rsyncable mode, + * which makes compressed files more rsync friendly + * by adding periodic synchronization points to the compressed data. + * The target average block size is ZSTD_c_jobSize / 2. + * It's possible to modify the job size to increase or decrease + * the granularity of the synchronization point. + * Once the jobSize is smaller than the window size, + * it will result in compression ratio degradation. + * NOTE 1: rsyncable mode only works when multithreading is enabled. + * NOTE 2: rsyncable performs poorly in combination with long range mode, + * since it will decrease the effectiveness of synchronization points, + * though mileage may vary. + * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s. + * If the selected compression level is already running significantly slower, + * the overall speed won't be significantly impacted. + */ + #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1 + +/* Select a compression format. + * The value must be of type ZSTD_format_e. + * See ZSTD_format_e enum definition for details */ +#define ZSTD_c_format ZSTD_c_experimentalParam2 + +/* Force back-reference distances to remain < windowSize, + * even when referencing into Dictionary content (default:0) */ +#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3 + +/* Controls whether the contents of a CDict + * are used in place, or copied into the working context. + * Accepts values from the ZSTD_dictAttachPref_e enum. + * See the comments on that enum for an explanation of the feature. */ +#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 + +/* Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never compress literals. + * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals + * may still be emitted if huffman is not beneficial to use.) + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * literals compression based on the compression parameters - specifically, + * negative compression levels do not use literal compression. + */ +#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 + +/* Tries to fit compressed block size to be around targetCBlockSize. + * No target when targetCBlockSize == 0. + * There is no guarantee on compressed block size (default:0) */ +#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6 + +/* User's best guess of source size. + * Hint is not valid when srcSizeHint == 0. + * There is no guarantee that hint is close to actual source size, + * but compression ratio may regress significantly if guess considerably underestimates */ +#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 + +/* Controls whether the new and experimental "dedicated dictionary search + * structure" can be used. This feature is still rough around the edges, be + * prepared for surprising behavior! + * + * How to use it: + * + * When using a CDict, whether to use this feature or not is controlled at + * CDict creation, and it must be set in a CCtxParams set passed into that + * construction (via ZSTD_createCDict_advanced2()). A compression will then + * use the feature or not based on how the CDict was constructed; the value of + * this param, set in the CCtx, will have no effect. + * + * However, when a dictionary buffer is passed into a CCtx, such as via + * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control + * whether the CDict that is created internally can use the feature or not. + * + * What it does: + * + * Normally, the internal data structures of the CDict are analogous to what + * would be stored in a CCtx after compressing the contents of a dictionary. + * To an approximation, a compression using a dictionary can then use those + * data structures to simply continue what is effectively a streaming + * compression where the simulated compression of the dictionary left off. + * Which is to say, the search structures in the CDict are normally the same + * format as in the CCtx. + * + * It is possible to do better, since the CDict is not like a CCtx: the search + * structures are written once during CDict creation, and then are only read + * after that, while the search structures in the CCtx are both read and + * written as the compression goes along. This means we can choose a search + * structure for the dictionary that is read-optimized. + * + * This feature enables the use of that different structure. + * + * Note that some of the members of the ZSTD_compressionParameters struct have + * different semantics and constraints in the dedicated search structure. It is + * highly recommended that you simply set a compression level in the CCtxParams + * you pass into the CDict creation call, and avoid messing with the cParams + * directly. + * + * Effects: + * + * This will only have any effect when the selected ZSTD_strategy + * implementation supports this feature. Currently, that's limited to + * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2. + * + * Note that this means that the CDict tables can no longer be copied into the + * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be + * usable. The dictionary can only be attached or reloaded. + * + * In general, you should expect compression to be faster--sometimes very much + * so--and CDict creation to be slightly slower. Eventually, we will probably + * make this mode the default. + */ +#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8 + +/* ZSTD_c_stableInBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the compressor that input data presented with ZSTD_inBuffer + * will ALWAYS be the same between calls. + * Technically, the @src pointer must never be changed, + * and the @pos field can only be updated by zstd. + * However, it's possible to increase the @size field, + * allowing scenarios where more data can be appended after compressions starts. + * These conditions are checked by the compressor, + * and compression will fail if they are not respected. + * Also, data in the ZSTD_inBuffer within the range [src, src + pos) + * MUST not be modified during compression or it will result in data corruption. + * + * When this flag is enabled zstd won't allocate an input window buffer, + * because the user guarantees it can reference the ZSTD_inBuffer until + * the frame is complete. But, it will still allocate an output buffer + * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also + * avoid the memcpy() from the input buffer to the input window buffer. + * + * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, compression WILL fail if conditions are not respected. + * + * WARNING: The data in the ZSTD_inBuffer in the range [src, src + pos) MUST + * not be modified during compression or it will result in data corruption. + * This is because zstd needs to reference data in the ZSTD_inBuffer to find + * matches. Normally zstd maintains its own window buffer for this purpose, + * but passing this flag tells zstd to rely on user provided buffer instead. + */ +#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9 + +/* ZSTD_c_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells he compressor that the ZSTD_outBuffer will not be resized between + * calls. Specifically: (out.size - out.pos) will never grow. This gives the + * compressor the freedom to say: If the compressed data doesn't fit in the + * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to + * always decompress directly into the output buffer, instead of decompressing + * into an internal buffer and copying to the output buffer. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer. It will still allocate the + * input window buffer (see ZSTD_c_stableInBuffer). + * + * Zstd will check that (out.size - out.pos) never grows and return an error + * if it does. While not strictly necessary, this should prevent surprises. + */ +#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10 + +/* ZSTD_c_blockDelimiters + * Default is 0 == ZSTD_sf_noBlockDelimiters. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * + * Designates whether or not the given array of ZSTD_Sequence contains block delimiters + * and last literals, which are defined as sequences with offset == 0 and matchLength == 0. + * See the definition of ZSTD_Sequence for more specifics. + */ +#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11 + +/* ZSTD_c_validateSequences + * Default is 0 == disabled. Set to 1 to enable sequence validation. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * Designates whether or not we validate sequences provided to ZSTD_compressSequences() + * during function execution. + * + * Without validation, providing a sequence that does not conform to the zstd spec will cause + * undefined behavior, and may produce a corrupted block. + * + * With validation enabled, if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and + * return an error. + * + */ +#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 + +/* ZSTD_c_useBlockSplitter + * Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never use block splitter. + * Set to ZSTD_ps_enable to always use block splitter. + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * block splitting based on the compression parameters. + */ +#define ZSTD_c_useBlockSplitter ZSTD_c_experimentalParam13 + +/* ZSTD_c_useRowMatchFinder + * Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never use row-based matchfinder. + * Set to ZSTD_ps_enable to force usage of row-based matchfinder. + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * the row-based matchfinder based on support for SIMD instructions and the window log. + * Note that this only pertains to compression strategies: greedy, lazy, and lazy2 + */ +#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14 + +/* ZSTD_c_deterministicRefPrefix + * Default is 0 == disabled. Set to 1 to enable. + * + * Zstd produces different results for prefix compression when the prefix is + * directly adjacent to the data about to be compressed vs. when it isn't. + * This is because zstd detects that the two buffers are contiguous and it can + * use a more efficient match finding algorithm. However, this produces different + * results than when the two buffers are non-contiguous. This flag forces zstd + * to always load the prefix in non-contiguous mode, even if it happens to be + * adjacent to the data, to guarantee determinism. + * + * If you really care about determinism when using a dictionary or prefix, + * like when doing delta compression, you should select this option. It comes + * at a speed penalty of about ~2.5% if the dictionary and data happened to be + * contiguous, and is free if they weren't contiguous. We don't expect that + * intentionally making the dictionary and data contiguous will be worth the + * cost to memcpy() the data. + */ +#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15 + +/* ZSTD_c_prefetchCDictTables + * Controlled with ZSTD_paramSwitch_e enum. Default is ZSTD_ps_auto. + * + * In some situations, zstd uses CDict tables in-place rather than copying them + * into the working context. (See docs on ZSTD_dictAttachPref_e above for details). + * In such situations, compression speed is seriously impacted when CDict tables are + * "cold" (outside CPU cache). This parameter instructs zstd to prefetch CDict tables + * when they are used in-place. + * + * For sufficiently small inputs, the cost of the prefetch will outweigh the benefit. + * For sufficiently large inputs, zstd will by default memcpy() CDict tables + * into the working context, so there is no need to prefetch. This parameter is + * targeted at a middle range of input sizes, where a prefetch is cheap enough to be + * useful but memcpy() is too expensive. The exact range of input sizes where this + * makes sense is best determined by careful experimentation. + * + * Note: for this parameter, ZSTD_ps_auto is currently equivalent to ZSTD_ps_disable, + * but in the future zstd may conditionally enable this feature via an auto-detection + * heuristic for cold CDicts. + * Use ZSTD_ps_disable to opt out of prefetching under any circumstances. + */ +#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16 + +/* ZSTD_c_enableSeqProducerFallback + * Allowed values are 0 (disable) and 1 (enable). The default setting is 0. + * + * Controls whether zstd will fall back to an internal sequence producer if an + * external sequence producer is registered and returns an error code. This fallback + * is block-by-block: the internal sequence producer will only be called for blocks + * where the external sequence producer returns an error code. Fallback parsing will + * follow any other cParam settings, such as compression level, the same as in a + * normal (fully-internal) compression operation. + * + * The user is strongly encouraged to read the full Block-Level Sequence Producer API + * documentation (below) before setting this parameter. */ +#define ZSTD_c_enableSeqProducerFallback ZSTD_c_experimentalParam17 + +/* ZSTD_c_maxBlockSize + * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB). + * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default. + * + * This parameter can be used to set an upper bound on the blocksize + * that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper + * bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make + * compressBound() inaccurate). Only currently meant to be used for testing. + * + */ +#define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18 + +/* ZSTD_c_searchForExternalRepcodes + * This parameter affects how zstd parses external sequences, such as sequences + * provided through the compressSequences() API or from an external block-level + * sequence producer. + * + * If set to ZSTD_ps_enable, the library will check for repeated offsets in + * external sequences, even if those repcodes are not explicitly indicated in + * the "rep" field. Note that this is the only way to exploit repcode matches + * while using compressSequences() or an external sequence producer, since zstd + * currently ignores the "rep" field of external sequences. + * + * If set to ZSTD_ps_disable, the library will not exploit repeated offsets in + * external sequences, regardless of whether the "rep" field has been set. This + * reduces sequence compression overhead by about 25% while sacrificing some + * compression ratio. + * + * The default value is ZSTD_ps_auto, for which the library will enable/disable + * based on compression level. + * + * Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is + * set to ZSTD_sf_explicitBlockDelimiters. That may change in the future. + */ +#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 + +/*! ZSTD_CCtx_getParameter() : + * Get the requested compression parameter value, selected by enum ZSTD_cParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); + + +/*! ZSTD_CCtx_params : + * Quick howto : + * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure + * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into + * an existing ZSTD_CCtx_params structure. + * This is similar to + * ZSTD_CCtx_setParameter(). + * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to + * an existing CCtx. + * These parameters will be applied to + * all subsequent frames. + * - ZSTD_compressStream2() : Do compression using the CCtx. + * - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer. + * + * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() + * for static allocation of CCtx for single-threaded compression. + */ +ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); +ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */ + +/*! ZSTD_CCtxParams_reset() : + * Reset params to default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); + +/*! ZSTD_CCtxParams_init() : + * Initializes the compression parameters of cctxParams according to + * compression level. All other parameters are reset to their default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); + +/*! ZSTD_CCtxParams_init_advanced() : + * Initializes the compression and frame parameters of cctxParams according to + * params. All other parameters are reset to their default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); + +/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+ + * Similar to ZSTD_CCtx_setParameter. + * Set one compression parameter, selected by enum ZSTD_cParameter. + * Parameters must be applied to a ZSTD_CCtx using + * ZSTD_CCtx_setParametersUsingCCtxParams(). + * @result : a code representing success or failure (which can be tested with + * ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtxParams_getParameter() : + * Similar to ZSTD_CCtx_getParameter. + * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); + +/*! ZSTD_CCtx_setParametersUsingCCtxParams() : + * Apply a set of ZSTD_CCtx_params to the compression context. + * This can be done even after compression is started, + * if nbWorkers==0, this will have no impact until a new compression is started. + * if nbWorkers>=1, new parameters will be picked up at next job, + * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( + ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); + +/*! ZSTD_compressStream2_simpleArgs() : + * Same as ZSTD_compressStream2(), + * but using only integral types as arguments. + * This variant might be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs ( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos, + ZSTD_EndDirective endOp); + + +/*************************************** +* Advanced decompression functions +***************************************/ + +/*! ZSTD_isFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. + * Note 3 : Skippable Frame Identifiers are considered valid. */ +ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size); + +/*! ZSTD_createDDict_byReference() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * Dictionary content is referenced, and therefore stays in dictBuffer. + * It is important that dictBuffer outlives DDict, + * it must remain read accessible throughout the lifetime of DDict */ +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_byReference() : + * Same as ZSTD_DCtx_loadDictionary(), + * but references `dict` content instead of copying it into `dctx`. + * This saves memory if `dict` remains around., + * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_advanced() : + * Same as ZSTD_DCtx_loadDictionary(), + * but gives direct control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ +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); + +/*! ZSTD_DCtx_refPrefix_advanced() : + * Same as ZSTD_DCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_DCtx_setMaxWindowSize() : + * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. + * This protects a decoder context from reserving too much memory for itself (potential attack scenario). + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); + +/*! ZSTD_DCtx_getParameter() : + * Get the requested decompression parameter value, selected by enum ZSTD_dParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value); + +/* ZSTD_d_format + * experimental parameter, + * allowing selection between ZSTD_format_e input compression formats + */ +#define ZSTD_d_format ZSTD_d_experimentalParam1 +/* ZSTD_d_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same + * between calls, except for the modifications that zstd makes to pos (the + * caller must not modify pos). This is checked by the decompressor, and + * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer + * MUST be large enough to fit the entire decompressed frame. This will be + * checked when the frame content size is known. The data in the ZSTD_outBuffer + * in the range [dst, dst + pos) MUST not be modified during decompression + * or you will get data corruption. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer, but it will still allocate + * an input buffer large enough to fit any compressed block. This will also + * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer. + * If you need to avoid the input buffer allocation use the buffer-less + * streaming API. + * + * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, decompression WILL fail if you violate the preconditions. + * + * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST + * not be modified during decompression or you will get data corruption. This + * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate + * matches. Normally zstd maintains its own buffer for this purpose, but passing + * this flag tells zstd to use the user provided buffer. + */ +#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 + +/* ZSTD_d_forceIgnoreChecksum + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * Tells the decompressor to skip checksum validation during decompression, regardless + * of whether checksumming was specified during compression. This offers some + * slight performance benefits, and may be useful for debugging. + * Param has values of type ZSTD_forceIgnoreChecksum_e + */ +#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3 + +/* ZSTD_d_refMultipleDDicts + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * If enabled and dctx is allocated on the heap, then additional memory will be allocated + * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict() + * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead + * store all references. At decompression time, the appropriate dictID is selected + * from the set of DDicts based on the dictID in the frame. + * + * Usage is simply calling ZSTD_refDDict() on multiple dict buffers. + * + * Param has values of byte ZSTD_refMultipleDDicts_e + * + * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory + * allocation for the hash table. ZSTD_freeDCtx() also frees this memory. + * Memory is allocated as per ZSTD_DCtx::customMem. + * + * Although this function allocates memory for the table, the user is still responsible for + * memory management of the underlying ZSTD_DDict* themselves. + */ +#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4 + +/* ZSTD_d_disableHuffmanAssembly + * Set to 1 to disable the Huffman assembly implementation. + * The default value is 0, which allows zstd to use the Huffman assembly + * implementation if available. + * + * This parameter can be used to disable Huffman assembly at runtime. + * If you want to disable it at compile time you can define the macro + * ZSTD_DISABLE_ASM. + */ +#define ZSTD_d_disableHuffmanAssembly ZSTD_d_experimentalParam5 + + +/*! ZSTD_DCtx_setFormat() : + * This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter(). + * Instruct the decoder context about what kind of data to decode next. + * This instruction is mandatory to decode data without a fully-formed header, + * such ZSTD_f_zstd1_magicless for example. + * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ +ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead") +ZSTDLIB_STATIC_API +size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); + +/*! ZSTD_decompressStream_simpleArgs() : + * Same as ZSTD_decompressStream(), + * but using only integral types as arguments. + * This can be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs ( + ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos); + + +/******************************************************************** +* Advanced streaming functions +* Warning : most of these functions are now redundant with the Advanced API. +* Once Advanced API reaches "stable" status, +* redundant functions will be deprecated, and then at some point removed. +********************************************************************/ + +/*===== Advanced Streaming compression functions =====*/ + +/*! ZSTD_initCStream_srcSize() : + * This function is DEPRECATED, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * + * pledgedSrcSize must be correct. If it is not known at init time, use + * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, + * "0" also disables frame content size field. It may be enabled in the future. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, + int compressionLevel, + unsigned long long pledgedSrcSize); + +/*! ZSTD_initCStream_usingDict() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * Creates of an internal CDict (incompatible with static CCtx), except if + * dict == NULL or dictSize < 8, in which case no dict is used. + * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if + * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + int compressionLevel); + +/*! ZSTD_initCStream_advanced() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setParams(zcs, params); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. + * pledgedSrcSize must be correct. + * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + ZSTD_parameters params, + unsigned long long pledgedSrcSize); + +/*! ZSTD_initCStream_usingCDict() : + * This function is DEPRECATED, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * note : cdict will just be referenced, and must outlive compression session + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); + +/*! ZSTD_initCStream_usingCDict_advanced() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setFParams(zcs, fParams); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. + * pledgedSrcSize must be correct. If srcSize is not known at init time, use + * value ZSTD_CONTENTSIZE_UNKNOWN. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams, + unsigned long long pledgedSrcSize); + +/*! ZSTD_resetCStream() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but + * ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be + * explicitly specified. + * + * start a new frame, using same parameters from previous frame. + * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. + * Note that zcs must be init at least once before using ZSTD_resetCStream(). + * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. + * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. + * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, + * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. + * @return : 0, or an error code (which can be tested using ZSTD_isError()) + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); + + +typedef struct { + unsigned long long ingested; /* nb input bytes read and buffered */ + unsigned long long consumed; /* nb input bytes actually compressed */ + unsigned long long produced; /* nb of compressed bytes generated and buffered */ + unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ + unsigned currentJobID; /* MT only : latest started job nb */ + unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ +} ZSTD_frameProgression; + +/* ZSTD_getFrameProgression() : + * tells how much data has been ingested (read from input) + * consumed (input actually compressed) and produced (output) for current frame. + * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. + * Aggregates progression inside active worker threads. + */ +ZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); + +/*! ZSTD_toFlushNow() : + * Tell how many bytes are ready to be flushed immediately. + * Useful for multithreading scenarios (nbWorkers >= 1). + * Probe the oldest active job, defined as oldest job not yet entirely flushed, + * and check its output buffer. + * @return : amount of data stored in oldest job and ready to be flushed immediately. + * if @return == 0, it means either : + * + there is no active job (could be checked with ZSTD_frameProgression()), or + * + oldest job is still actively compressing data, + * but everything it has produced has also been flushed so far, + * therefore flush speed is limited by production speed of oldest job + * irrespective of the speed of concurrent (and newer) jobs. + */ +ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); + + +/*===== Advanced Streaming decompression functions =====*/ + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_loadDictionary(zds, dict, dictSize); + * + * note: no dictionary will be used if dict == NULL or dictSize < 8 + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, ddict); + * + * note : ddict is referenced, it must outlive decompression session + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * + * re-use decompression parameters from previous init; saves dictionary loading + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); + + +/* ********************* BLOCK-LEVEL SEQUENCE PRODUCER API ********************* + * + * *** OVERVIEW *** + * The Block-Level Sequence Producer API allows users to provide their own custom + * sequence producer which libzstd invokes to process each block. The produced list + * of sequences (literals and matches) is then post-processed by libzstd to produce + * valid compressed blocks. + * + * This block-level offload API is a more granular complement of the existing + * frame-level offload API compressSequences() (introduced in v1.5.1). It offers + * an easier migration story for applications already integrated with libzstd: the + * user application continues to invoke the same compression functions + * ZSTD_compress2() or ZSTD_compressStream2() as usual, and transparently benefits + * from the specific advantages of the external sequence producer. For example, + * the sequence producer could be tuned to take advantage of known characteristics + * of the input, to offer better speed / ratio, or could leverage hardware + * acceleration not available within libzstd itself. + * + * See contrib/externalSequenceProducer for an example program employing the + * Block-Level Sequence Producer API. + * + * *** USAGE *** + * The user is responsible for implementing a function of type + * ZSTD_sequenceProducer_F. For each block, zstd will pass the following + * arguments to the user-provided function: + * + * - sequenceProducerState: a pointer to a user-managed state for the sequence + * producer. + * + * - outSeqs, outSeqsCapacity: an output buffer for the sequence producer. + * outSeqsCapacity is guaranteed >= ZSTD_sequenceBound(srcSize). The memory + * backing outSeqs is managed by the CCtx. + * + * - src, srcSize: an input buffer for the sequence producer to parse. + * srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX. + * + * - dict, dictSize: a history buffer, which may be empty, which the sequence + * producer may reference as it parses the src buffer. Currently, zstd will + * always pass dictSize == 0 into external sequence producers, but this will + * change in the future. + * + * - compressionLevel: a signed integer representing the zstd compression level + * set by the user for the current operation. The sequence producer may choose + * to use this information to change its compression strategy and speed/ratio + * tradeoff. Note: the compression level does not reflect zstd parameters set + * through the advanced API. + * + * - windowSize: a size_t representing the maximum allowed offset for external + * sequences. Note that sequence offsets are sometimes allowed to exceed the + * windowSize if a dictionary is present, see doc/zstd_compression_format.md + * for details. + * + * The user-provided function shall return a size_t representing the number of + * sequences written to outSeqs. This return value will be treated as an error + * code if it is greater than outSeqsCapacity. The return value must be non-zero + * if srcSize is non-zero. The ZSTD_SEQUENCE_PRODUCER_ERROR macro is provided + * for convenience, but any value greater than outSeqsCapacity will be treated as + * an error code. + * + * If the user-provided function does not return an error code, the sequences + * written to outSeqs must be a valid parse of the src buffer. Data corruption may + * occur if the parse is not valid. A parse is defined to be valid if the + * following conditions hold: + * - The sum of matchLengths and literalLengths must equal srcSize. + * - All sequences in the parse, except for the final sequence, must have + * matchLength >= ZSTD_MINMATCH_MIN. The final sequence must have + * matchLength >= ZSTD_MINMATCH_MIN or matchLength == 0. + * - All offsets must respect the windowSize parameter as specified in + * doc/zstd_compression_format.md. + * - If the final sequence has matchLength == 0, it must also have offset == 0. + * + * zstd will only validate these conditions (and fail compression if they do not + * hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence + * validation has a performance cost. + * + * If the user-provided function returns an error, zstd will either fall back + * to an internal sequence producer or fail the compression operation. The user can + * choose between the two behaviors by setting the ZSTD_c_enableSeqProducerFallback + * cParam. Fallback compression will follow any other cParam settings, such as + * compression level, the same as in a normal compression operation. + * + * The user shall instruct zstd to use a particular ZSTD_sequenceProducer_F + * function by calling + * ZSTD_registerSequenceProducer(cctx, + * sequenceProducerState, + * sequenceProducer) + * This setting will persist until the next parameter reset of the CCtx. + * + * The sequenceProducerState must be initialized by the user before calling + * ZSTD_registerSequenceProducer(). The user is responsible for destroying the + * sequenceProducerState. + * + * *** LIMITATIONS *** + * This API is compatible with all zstd compression APIs which respect advanced parameters. + * However, there are three limitations: + * + * First, the ZSTD_c_enableLongDistanceMatching cParam is not currently supported. + * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with a block-level + * external sequence producer. + * - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in some + * cases (see its documentation for details). Users must explicitly set + * ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an external + * sequence producer is registered. + * - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default + * whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should + * check the docs on ZSTD_c_enableLongDistanceMatching whenever the Block-Level Sequence + * Producer API is used in conjunction with advanced settings (like ZSTD_c_windowLog). + * + * Second, history buffers are not currently supported. Concretely, zstd will always pass + * dictSize == 0 to the external sequence producer (for now). This has two implications: + * - Dictionaries are not currently supported. Compression will *not* fail if the user + * references a dictionary, but the dictionary won't have any effect. + * - Stream history is not currently supported. All advanced compression APIs, including + * streaming APIs, work with external sequence producers, but each block is treated as + * an independent chunk without history from previous blocks. + * + * Third, multi-threading within a single compression is not currently supported. In other words, + * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external sequence producer is registered. + * Multi-threading across compressions is fine: simply create one CCtx per thread. + * + * Long-term, we plan to overcome all three limitations. There is no technical blocker to + * overcoming them. It is purely a question of engineering effort. + */ + +#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1)) + +typedef size_t ZSTD_sequenceProducer_F ( + void* sequenceProducerState, + ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, + const void* src, size_t srcSize, + const void* dict, size_t dictSize, + int compressionLevel, + size_t windowSize +); + +/*! ZSTD_registerSequenceProducer() : + * Instruct zstd to use a block-level external sequence producer function. + * + * The sequenceProducerState must be initialized by the caller, and the caller is + * responsible for managing its lifetime. This parameter is sticky across + * compressions. It will remain set until the user explicitly resets compression + * parameters. + * + * Sequence producer registration is considered to be an "advanced parameter", + * part of the "advanced API". This means it will only have an effect on compression + * APIs which respect advanced parameters, such as compress2() and compressStream2(). + * Older compression APIs such as compressCCtx(), which predate the introduction of + * "advanced parameters", will ignore any external sequence producer setting. + * + * The sequence producer can be "cleared" by registering a NULL function pointer. This + * removes all limitations described above in the "LIMITATIONS" section of the API docs. + * + * The user is strongly encouraged to read the full API documentation (above) before + * calling this function. */ +ZSTDLIB_STATIC_API void +ZSTD_registerSequenceProducer( + ZSTD_CCtx* cctx, + void* sequenceProducerState, + ZSTD_sequenceProducer_F* sequenceProducer +); + + +/********************************************************************* +* Buffer-less and synchronous inner streaming functions (DEPRECATED) +* +* This API is deprecated, and will be removed in a future version. +* It allows streaming (de)compression with user allocated buffers. +* However, it is hard to use, and not as well tested as the rest of +* our API. +* +* Please use the normal streaming API instead: ZSTD_compressStream2, +* and ZSTD_decompressStream. +* If there is functionality that you need, but it doesn't provide, +* please open an issue on our GitHub. +********************************************************************* */ + +/** + Buffer-less streaming compression (synchronous mode) + + A ZSTD_CCtx object is required to track streaming operations. + Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. + ZSTD_CCtx object can be re-used multiple times within successive compression operations. + + Start by initializing a context. + Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression. + + Then, consume your input using ZSTD_compressContinue(). + There are some important considerations to keep in mind when using this advanced function : + - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. + - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. + - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. + Worst case evaluation is provided by ZSTD_compressBound(). + ZSTD_compressContinue() doesn't guarantee recover after a failed compression. + - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). + It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) + - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. + In which case, it will "discard" the relevant memory section from its history. + + Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. + It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. + Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. + + `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again. +*/ + +/*===== Buffer-less streaming compression functions =====*/ +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ + +ZSTD_DEPRECATED("This function will likely be removed in a future release. It is misleading and has very limited utility.") +ZSTDLIB_STATIC_API +size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +ZSTDLIB_STATIC_API +size_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 */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +ZSTDLIB_STATIC_API +size_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 */ +/** + Buffer-less streaming decompression (synchronous mode) + + A ZSTD_DCtx object is required to track streaming operations. + Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. + A ZSTD_DCtx object can be re-used multiple times. + + First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). + Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. + Data fragment must be large enough to ensure successful decoding. + `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. + result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. + >0 : `srcSize` is too small, please provide at least result bytes on next attempt. + errorCode, which can be tested using ZSTD_isError(). + + It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). + Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. + As a consequence, check that values remain within valid application range. + For example, do not allocate memory blindly, check that `windowSize` is within expectation. + Each application can set its own limits, depending on local restrictions. + For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. + + ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. + ZSTD_decompressContinue() is very sensitive to contiguity, + if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, + or that previous contiguous segment is large enough to properly handle maximum back-reference distance. + There are multiple ways to guarantee this condition. + + The most memory efficient way is to use a round buffer of sufficient size. + Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), + which can return an error code if required value is too large for current system (in 32-bits mode). + In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, + up to the moment there is not enough room left in the buffer to guarantee decoding another full block, + which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. + At which point, decoding can resume from the beginning of the buffer. + Note that already decoded data stored in the buffer should be flushed before being overwritten. + + There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. + + Finally, if you control the compression process, you can also ignore all buffer size rules, + as long as the encoder and decoder progress in "lock-step", + aka use exactly the same buffer sizes, break contiguity at the same place, etc. + + Once buffers are setup, start decompression, with ZSTD_decompressBegin(). + If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). + + Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. + ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. + + result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). + It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. + It can also be an error code, which can be tested with ZSTD_isError(). + + A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. + Context can then be reset to start a new decompression. + + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + This information is not required to properly decode a frame. + + == Special case : skippable frames == + + Skippable frames allow integration of user-defined data into a flow of concatenated frames. + Skippable frames will be ignored (skipped) by decompressor. + The format of skippable frames is as follows : + a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F + b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits + c) Frame Content - any content (User Data) of length equal to Frame Size + For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. + For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. +*/ + +/*===== Buffer-less streaming decompression functions =====*/ + +ZSTDLIB_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 */ + +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +ZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); +ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* misc */ +ZSTD_DEPRECATED("This function will likely be removed in the next minor release. It is misleading and has very limited utility.") +ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + + + + +/* ========================================= */ +/** Block level API (DEPRECATED) */ +/* ========================================= */ + +/*! + + This API is deprecated in favor of the regular compression API. + You can get the frame header down to 2 bytes by setting: + - ZSTD_c_format = ZSTD_f_zstd1_magicless + - ZSTD_c_contentSizeFlag = 0 + - ZSTD_c_checksumFlag = 0 + - ZSTD_c_dictIDFlag = 0 + + This API is not as well tested as our normal API, so we recommend not using it. + We will be removing it in a future version. If the normal API doesn't provide + the functionality you need, please open a GitHub issue. + + Block functions produce and decode raw zstd blocks, without frame metadata. + Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes). + But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes. + + A few rules to respect : + - Compressing and decompressing require a context structure + + Use ZSTD_createCCtx() and ZSTD_createDCtx() + - It is necessary to init context before starting + + compression : any ZSTD_compressBegin*() variant, including with dictionary + + decompression : any ZSTD_decompressBegin*() variant, including with dictionary + - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB + + If input is larger than a block size, it's necessary to split input data into multiple blocks + + For inputs larger than a single block, consider using regular ZSTD_compress() instead. + Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block. + - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) ! + ===> In which case, nothing is produced into `dst` ! + + User __must__ test for such outcome and deal directly with uncompressed data + + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0. + Doing so would mess up with statistics history, leading to potential data corruption. + + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !! + + In case of multiple successive blocks, should some of them be uncompressed, + decoder must be informed of their existence in order to follow proper history. + Use ZSTD_insertBlock() for such a case. +*/ + +/*===== Raw zstd block functions =====*/ +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_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. */ + +#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ + +#if defined (__cplusplus) +} +#endif diff --git a/sources/main.cpp b/sources/main.cpp index 167032f..b12e01e 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) } try { #ifdef SWFP_PACKER - sw::Packer::path = argv[1]; + sw::Packer::path = argv[1]; sw::File::countFiles(sw::Packer::path); sw::File::generateFile("packages"); diff --git a/sources/pack/Packer.cpp b/sources/pack/Packer.cpp index c2b6787..2a0e979 100644 --- a/sources/pack/Packer.cpp +++ b/sources/pack/Packer.cpp @@ -13,6 +13,7 @@ #include "FileException.hpp" #include "utils.hpp" #include "Log.hpp" +#include "zstd.hpp" std::string sw::Packer::path{}; @@ -55,11 +56,17 @@ void sw::Packer::createChunkData(std::string path, sw::chunkHeader& header, sw:: std::memcpy(data.path, path.data() + sw::Packer::path.size(), path.size() - sw::Packer::path.size()); data.pathCount = path.size() - sw::Packer::path.size(); fillProps(data); - data.data = sw::MemAlloc(size); - std::memcpy(data.data, buffer.data(), size); - header.sizeBase = size; +#ifdef SWFP_COMP + data.data = sw::MemAlloc(ZSTD_compressBound(size)); + header.sizePack = ZSTD_compress(data.data, ZSTD_compressBound(size), buffer.data(), size, 15); + if (ZSTD_isError(header.sizePack)) + throw sw::FileException("Unexpected error occur during compression process: " + std::string(ZSTD_getErrorName(header.sizePack))); +#else header.sizePack = size; + data.data = sw::MemAlloc(size); + std::memcpy(data.data, buffer.data(), size); +#endif } void sw::Packer::readFile(std::string path) diff --git a/sources/unpack/UnPackFile.cpp b/sources/unpack/UnPackFile.cpp index db0da79..f88d518 100644 --- a/sources/unpack/UnPackFile.cpp +++ b/sources/unpack/UnPackFile.cpp @@ -11,6 +11,7 @@ #include "FileException.hpp" #include "utils.hpp" #include "Log.hpp" +#include "zstd.hpp" sw::UnPackFile::UnPackFile(std::string path, std::string outputPath) { @@ -52,10 +53,22 @@ void sw::UnPackFile::createFile(sw::chunkHeader &chunkHeader, std::string path, { std::filesystem::path p(outputPath + path); std::filesystem::create_directories(p.parent_path()); + +#ifdef SWFP_COMP + auto *bufferComp = (unsigned char*)sw::MemAlloc(chunkHeader.sizePack); + auto *buffer = (unsigned char*)sw::MemAlloc(ZSTD_compressBound(chunkHeader.sizeBase)); + + memset(bufferComp, '\0', chunkHeader.sizePack); + m_file.read((char *)bufferComp, chunkHeader.sizePack); + size_t sizeComp = ZSTD_decompress(buffer, ZSTD_compressBound(chunkHeader.sizeBase), bufferComp, chunkHeader.sizePack); + if (sizeComp != chunkHeader.sizeBase) + throw sw::FileException("File size id different"); +#else auto *buffer = (unsigned char*)sw::MemAlloc(chunkHeader.sizeBase); - memset(buffer, '\0', chunkHeader.sizeBase); - m_file.read((char *)buffer, chunkHeader.sizeBase); + memset(buffer, '\0', chunkHeader.sizePack); + m_file.read((char *)buffer, chunkHeader.sizePack); +#endif try { std::fstream outFile(outputPath + path, std::ios::out | std::ios::binary); if (!outFile.is_open()) From 9cc5185fb5ff48ed77a128f11cbb9e15a7acaac3 Mon Sep 17 00:00:00 2001 From: Guilaume S Date: Tue, 26 Sep 2023 11:12:12 +0200 Subject: [PATCH 2/5] Add option to build shared or static library for unpacker --- CMakeLists.txt | 2 ++ README.md | 2 ++ cmake/UnPacker.cmake | 19 ++++++++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 285e919..bda1fc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ message(${PREFIX_MESSAGE} "Project location: " ${CMAKE_SOURCE_DIR}) message(${PREFIX_MESSAGE} "Project system: " ${CMAKE_SYSTEM_NAME}) option(SWFP_COMP "Define if the packer will enable compact process" ) +option(BUILD_UNPACK_LIB_SHARED "Define if Unpacker is build as a library as shared" ) +option(BUILD_UNPACK_LIB_STATIC "Define if Unpacker is build as a library as static" ) ## IMPORTED STATIC LIBRARY NAME set( STATIC_LIB_NAME diff --git a/README.md b/README.md index 26d04ef..7e04ae9 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ cmake --build . --target SWEngine-[packer/unpacker]_1.1 --config [Debug/Release] You can define an option by using : `-D[option]=[value]` - CMAKE_BUILD_TYPE: Debug/Release - SWFP_COMP: ON/OFF +- BUILD_UNPACK_LIB_SHARED: ON/OFF +- BUILD_UNPACK_LIB_STATIC: ON/OFF ## Usage ### Packer diff --git a/cmake/UnPacker.cmake b/cmake/UnPacker.cmake index 4c17552..d456223 100644 --- a/cmake/UnPacker.cmake +++ b/cmake/UnPacker.cmake @@ -36,8 +36,21 @@ file(GLOB SRC ${TMP}) ## OUTPUT ## <=====================================> -## EXECUTABLE -add_executable(${EXEC} ${SRC}) + +if (NOT ${BUILD_UNPACK_LIB_SHARED} AND NOT ${BUILD_UNPACK_LIB_STATIC}) + ## EXECUTABLE + add_executable(${EXEC} ${SRC}) + message(${PREFIX_MESSAGE} "Unpacker build as executable") +elseif (${BUILD_UNPACK_LIB_SHARED}) + ## SHARED LIB + add_library(${EXEC} SHARED ${SRC}) + message(${PREFIX_MESSAGE} "Unpacker build as Shared library") +elseif (${BUILD_UNPACK_LIB_STATIC}) + ## STATIC LIB + add_library(${EXEC} STATIC ${SRC}) + message(${PREFIX_MESSAGE} "Unpacker build as Static library") +endif () + ## <=====================================> target_compile_definitions(${EXEC} PUBLIC "SWFP_UNPACKER") @@ -58,7 +71,7 @@ endif() ## STATIC LIBRARY LINKING ## <=====================================> -if (${STATIC_LIB_NAME}) +if (NOT ${STATIC_LIB_NAME} STREQUAL "") target_link_libraries(${EXEC} PUBLIC ${STATIC_LIB_NAME} From 1ee60c3c4d3d3208984f8e73c2d4d69340594b3c Mon Sep 17 00:00:00 2001 From: Guilaume S Date: Tue, 26 Sep 2023 11:22:08 +0200 Subject: [PATCH 3/5] Update action add build for library --- .github/workflows/Test_windows.yml | 49 ++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Test_windows.yml b/.github/workflows/Test_windows.yml index 6b110c8..498d720 100644 --- a/.github/workflows/Test_windows.yml +++ b/.github/workflows/Test_windows.yml @@ -12,9 +12,10 @@ on: env: BUILD_TYPE: Release + VERSION_NAME: 1.1 jobs: - Test_windows: + Build_exec: runs-on: windows-latest steps: - name: Checkout repository @@ -34,4 +35,48 @@ jobs: uses: actions/upload-artifact@v3 with: name: SWPacker - path: ${{github.workspace}}\out\1.1\Release\ \ No newline at end of file + path: ${{github.workspace}}\out\${{env.VERSION_NAME}}\Release\ + + Build_Unpack_Shared: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Config executables + run: | + mkdir build && cd build + cmake -B ${{github.workspace}}\build -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_UNPACK_LIB_SHARED=ON .. + + - name: Build executables + run: | + cd ${{github.workspace}}\build + cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}} + + - name: Archive Library + uses: actions/upload-artifact@v3 + with: + name: SWPacker + path: ${{github.workspace}}\out\${{env.VERSION_NAME}}\Release\ + + Build_Unpack_Static: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Config executables + run: | + mkdir build && cd build + cmake -B ${{github.workspace}}\build -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_UNPACK_LIB_STATIC=ON .. + + - name: Build executables + run: | + cd ${{github.workspace}}\build + cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}} + + - name: Archive library + uses: actions/upload-artifact@v3 + with: + name: SWPacker + path: ${{github.workspace}}\out\${{env.VERSION_NAME}}\Release\ \ No newline at end of file From fa305769d5c59ce4b222860bf7e314efda9195b9 Mon Sep 17 00:00:00 2001 From: Guilaume S Date: Tue, 26 Sep 2023 11:51:15 +0200 Subject: [PATCH 4/5] Remove reference to zstd in packer cmake --- .github/workflows/Test_windows.yml | 4 ++-- CMakeLists.txt | 1 - cmake/Packer.cmake | 10 ---------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/Test_windows.yml b/.github/workflows/Test_windows.yml index 498d720..fc94d33 100644 --- a/.github/workflows/Test_windows.yml +++ b/.github/workflows/Test_windows.yml @@ -51,7 +51,7 @@ jobs: - name: Build executables run: | cd ${{github.workspace}}\build - cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}} + cmake --build ${{github.workspace}}\build --target SWEngine-unpacker_${{env.VERSION_NAME}} --config ${{env.BUILD_TYPE}} - name: Archive Library uses: actions/upload-artifact@v3 @@ -73,7 +73,7 @@ jobs: - name: Build executables run: | cd ${{github.workspace}}\build - cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}} + cmake --build ${{github.workspace}}\build --target SWEngine-unpacker_${{env.VERSION_NAME}} --config ${{env.BUILD_TYPE}} - name: Archive library uses: actions/upload-artifact@v3 diff --git a/CMakeLists.txt b/CMakeLists.txt index bda1fc6..2b745e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,6 @@ list(LENGTH STATIC_LIB_NAME list_len) math(EXPR LIST_LEN "${list_len} - 1") if (${LIST_LEN} GREATER_EQUAL 0) - foreach(ctr RANGE ${LIST_LEN}) list(GET STATIC_LIB_NAME ${ctr} lib) list(GET STATIC_LIB ${ctr} filelib) diff --git a/cmake/Packer.cmake b/cmake/Packer.cmake index 2b4e51b..ba30fbb 100644 --- a/cmake/Packer.cmake +++ b/cmake/Packer.cmake @@ -59,16 +59,6 @@ if(MSVC) endif() ## <=====================================> -## IMPORTED STATIC LIBRARY NAME -set( STATIC_LIB_NAME - zstd_static - ) - -## IMPORTED STATIC LIBRARY .lib file -set( STATIC_LIB - ${CMAKE_SOURCE_DIR}/libraries/zstd_static.lib - ) - ## STATIC LIBRARY LINKING ## <=====================================> if (${STATIC_LIB_NAME}) From 522e4e2f816ae32b37f94f99144ad9185b9c13d9 Mon Sep 17 00:00:00 2001 From: Guilaume S Date: Tue, 26 Sep 2023 12:09:55 +0200 Subject: [PATCH 5/5] Update action change artefact name Update ReadMe add logo on the top --- .github/resources/images/logo.png | Bin 0 -> 124587 bytes .github/workflows/Test_windows.yml | 11 +++++++---- README.md | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 .github/resources/images/logo.png diff --git a/.github/resources/images/logo.png b/.github/resources/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fb43cf43d9bc9e70ccb479680c524c588607d8b7 GIT binary patch literal 124587 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 + +

+ # SWPacker ## Description SWPacker is program that allow to pack all files from a directory.