268 lines
14 KiB
C
268 lines
14 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
// header version :
|
|
// the DLL is incompatible when MAJOR is bumped
|
|
// MINOR is for internal revs and bug fixes that don't affect API compatibility
|
|
// TODO: Check if the DLL gives a minor version
|
|
#define OODLE2_VERSION_MAJOR 8
|
|
#define OODLE2_VERSION_MINOR 14
|
|
|
|
// OodleVersion string is 1 . MAJOR . MINOR
|
|
// don't make it from macros cuz the doc tool has to parse the string literal
|
|
|
|
#define OodleVersion "2.8.14"
|
|
|
|
|
|
// Default verbosity selection of 0 will not even log when it sees corruption
|
|
// Verbosity of LZ functions
|
|
typedef enum OodleLZ_Verbosity {
|
|
OodleLZ_Verbosity_None = 0,
|
|
OodleLZ_Verbosity_Minimal = 1,
|
|
OodleLZ_Verbosity_Some = 2,
|
|
OodleLZ_Verbosity_Lots = 3,
|
|
OodleLZ_Verbosity_Force32 = 0x40000000
|
|
} OodleLZ_Verbosity;
|
|
|
|
|
|
typedef enum OodleLZ_Compressor {
|
|
OodleLZ_Compressor_Invalid = -1,
|
|
OodleLZ_Compressor_None = 3, // None = memcpy, pass through uncompressed bytes
|
|
// NEW COMPRESSORS :
|
|
OodleLZ_Compressor_Kraken = 8, // Fast decompression and high compression ratios, amazing!
|
|
OodleLZ_Compressor_Leviathan = 13,// Leviathan = Kraken's big brother with higher compression, slightly slower decompression.
|
|
OodleLZ_Compressor_Mermaid = 9, // Mermaid is between Kraken & Selkie - crazy fast, still decent compression.
|
|
OodleLZ_Compressor_Selkie = 11, // Selkie is a super-fast relative of Mermaid. For maximum decode speed.
|
|
OodleLZ_Compressor_Hydra = 12, // Hydra, the many-headed beast = Leviathan, Kraken, Mermaid, or Selkie (see $OodleLZ_About_Hydra)
|
|
OodleLZ_Compressor_BitKnit = 10,
|
|
OodleLZ_Compressor_LZB16 = 4, // DEPRECATED but still supported
|
|
OodleLZ_Compressor_LZNA = 7,
|
|
OodleLZ_Compressor_LZH = 0,
|
|
OodleLZ_Compressor_LZHLW = 1,
|
|
OodleLZ_Compressor_LZNIB = 2,
|
|
OodleLZ_Compressor_LZBLW = 5,
|
|
OodleLZ_Compressor_LZA = 6,
|
|
OodleLZ_Compressor_Count = 14,
|
|
OodleLZ_Compressor_Force32 = 0x40000000
|
|
} OodleLZ_Compressor;
|
|
|
|
|
|
|
|
typedef enum OodleLZ_CheckCRC {
|
|
OodleLZ_CheckCRC_No = 0,
|
|
OodleLZ_CheckCRC_Yes = 1,
|
|
OodleLZ_CheckCRC_Force32 = 0x40000000
|
|
} OodleLZ_CheckCRC;
|
|
|
|
/* Selection of compression encoder complexity
|
|
|
|
Higher numerical value of CompressionLevel = slower compression, but smaller compressed data.
|
|
|
|
The compressed stream is always decodable with the same decompressors.
|
|
CompressionLevel controls the amount of work the encoder does to find the best compressed bit stream.
|
|
CompressionLevel does not primary affect decode speed, it trades off encode speed for compressed bit stream quality.
|
|
|
|
I recommend starting with OodleLZ_CompressionLevel_Normal, then try up or down if you want
|
|
faster encoding or smaller output files.
|
|
|
|
The Optimal levels are good for distribution when you compress rarely and decompress often;
|
|
they provide very high compression ratios but are slow to encode. Optimal2 is the recommended level
|
|
to start with of the optimal levels.
|
|
Optimal4 and 5 are not recommended for common use, they are very slow and provide the maximum compression ratio,
|
|
but the gain over Optimal3 is usually small.
|
|
|
|
The HyperFast levels have negative numeric CompressionLevel values.
|
|
They are faster than SuperFast for when you're encoder CPU time constrained or want
|
|
something closer to symmetric compression vs. decompression time.
|
|
The HyperFast levels are currently only available in Kraken, Mermaid & Selkie.
|
|
Higher levels of HyperFast are faster to encode, eg. HyperFast4 is the fastest.
|
|
|
|
The CompressionLevel does not affect decode speed much. Higher compression level does not mean
|
|
slower to decode. To trade off decode speed vs ratio, use _spaceSpeedTradeoffBytes_ in $OodleLZ_CompressOptions
|
|
*/
|
|
typedef enum OodleLZ_CompressionLevel {
|
|
OodleLZ_CompressionLevel_None = 0, // don't compress, just copy raw bytes
|
|
OodleLZ_CompressionLevel_SuperFast = 1, // super fast mode, lower compression ratio
|
|
OodleLZ_CompressionLevel_VeryFast = 2, // fastest LZ mode with still decent compression ratio
|
|
OodleLZ_CompressionLevel_Fast = 3, // fast - good for daily use
|
|
OodleLZ_CompressionLevel_Normal = 4, // standard medium speed LZ mode
|
|
|
|
OodleLZ_CompressionLevel_Optimal1 = 5, // optimal parse level 1 (faster optimal encoder)
|
|
OodleLZ_CompressionLevel_Optimal2 = 6, // optimal parse level 2 (recommended baseline optimal encoder)
|
|
OodleLZ_CompressionLevel_Optimal3 = 7, // optimal parse level 3 (slower optimal encoder)
|
|
OodleLZ_CompressionLevel_Optimal4 = 8, // optimal parse level 4 (very slow optimal encoder)
|
|
OodleLZ_CompressionLevel_Optimal5 = 9, // optimal parse level 5 (don't care about encode speed, maximum compression)
|
|
|
|
OodleLZ_CompressionLevel_HyperFast1 = -1, // faster than SuperFast, less compression
|
|
OodleLZ_CompressionLevel_HyperFast2 = -2, // faster than HyperFast1, less compression
|
|
OodleLZ_CompressionLevel_HyperFast3 = -3, // faster than HyperFast2, less compression
|
|
OodleLZ_CompressionLevel_HyperFast4 = -4, // fastest, less compression
|
|
|
|
// aliases :
|
|
OodleLZ_CompressionLevel_HyperFast = OodleLZ_CompressionLevel_HyperFast1, // alias hyperfast base level
|
|
OodleLZ_CompressionLevel_Optimal = OodleLZ_CompressionLevel_Optimal2, // alias optimal standard level
|
|
OodleLZ_CompressionLevel_Max = OodleLZ_CompressionLevel_Optimal5, // maximum compression level
|
|
OodleLZ_CompressionLevel_Min = OodleLZ_CompressionLevel_HyperFast4, // fastest compression level
|
|
|
|
OodleLZ_CompressionLevel_Force32 = 0x40000000,
|
|
OodleLZ_CompressionLevel_Invalid = OodleLZ_CompressionLevel_Force32
|
|
} OodleLZ_CompressionLevel;
|
|
|
|
|
|
typedef enum OodleLZ_Decode_ThreadPhase {
|
|
OodleLZ_Decode_ThreadPhase1 = 1,
|
|
OodleLZ_Decode_ThreadPhase2 = 2,
|
|
OodleLZ_Decode_ThreadPhaseAll = 3,
|
|
OodleLZ_Decode_Unthreaded = OodleLZ_Decode_ThreadPhaseAll
|
|
} OodleLZ_Decode_ThreadPhase;
|
|
|
|
|
|
typedef enum OodleLZ_FuzzSafe {
|
|
OodleLZ_FuzzSafe_No = 0,
|
|
OodleLZ_FuzzSafe_Yes = 1
|
|
} OodleLZ_FuzzSafe;
|
|
|
|
|
|
/* Compress some data from memory to memory, synchronously, with OodleLZ
|
|
|
|
$:compressor which OodleLZ variant to use in compression
|
|
$:rawBuf raw data to compress
|
|
$:rawLen number of bytes in rawBuf to compress
|
|
$:compBuf pointer to write compressed data to ; should be at least $OodleLZ_GetCompressedBufferSizeNeeded
|
|
$:level OodleLZ_CompressionLevel controls how much CPU effort is put into maximizing compression
|
|
$:pOptions (optional) options; if NULL, $OodleLZ_CompressOptions_GetDefault is used
|
|
$:dictionaryBase (optional) if not NULL, provides preceding data to prime the dictionary; must be contiguous with rawBuf, the data between the pointers _dictionaryBase_ and _rawBuf_ is used as the preconditioning data. The exact same precondition must be passed to encoder and decoder.
|
|
$:lrm (optional) long range matcher
|
|
$:scratchMem (optional) pointer to scratch memory
|
|
$:scratchSize (optional) size of scratch memory (see $OodleLZ_GetCompressScratchMemBound)
|
|
$:return size of compressed data written, or $OODLELZ_FAILED for failure
|
|
|
|
Performs synchronous memory to memory LZ compression.
|
|
|
|
In tools, you should generally use $OodleXLZ_Compress_AsyncAndWait instead to get parallelism. (in the Oodle2 Ext lib)
|
|
|
|
You can compress a large buffer in several calls by setting _dictionaryBase_ to the start
|
|
of the buffer, and then making _rawBuf_ and _rawLen_ select portions of that buffer. As long
|
|
as _rawLen_ is a multiple of $OODLELZ_BLOCK_LEN , the compressed chunks can simply be
|
|
concatenated together.
|
|
|
|
If _scratchMem_ is provided, it will be used for the compressor's scratch memory needs before OodleMalloc is
|
|
called. If the scratch is big enough, no malloc will be done. If the scratch is not big enough, the compress
|
|
will not fail, instead OodleMalloc will be used. OodleMalloc should not return null. There is currently no way
|
|
to make compress fail cleanly due to using too much memory, it must either succeed or abort the process.
|
|
|
|
If _scratchSize_ is at least $OodleLZ_GetCompressScratchMemBound , additional allocations will not be needed.
|
|
|
|
See $OodleLZ_About for tips on setting the compression options.
|
|
|
|
If _dictionaryBase_ is provided, the backup distance from _rawBuf_ must be a multiple of $OODLELZ_BLOCK_LEN
|
|
|
|
If $(OodleLZ_CompressOptions:seekChunkReset) is enabled, and _dictionaryBase_ is not NULL or _rawBuf_ , then the
|
|
seek chunk boundaries are relative to _dictionaryBase_, not to _rawBuf_.
|
|
|
|
*/
|
|
int OodleLZ_Compress(
|
|
OodleLZ_Compressor compressor,
|
|
const void* raw_buffer,
|
|
size_t raw_len,
|
|
void* compressed_buffer,
|
|
OodleLZ_CompressionLevel level,
|
|
void* options, // Default: null
|
|
size_t dictionary_base, // Default: null
|
|
const void* lrm, // Default: null
|
|
void* scratch_memory, // Default: null
|
|
size_t scratch_size // Default: null
|
|
);
|
|
|
|
// Decompress returns raw (decompressed) len received
|
|
// Decompress returns 0 (OODLELZ_FAILED) if it detects corruption
|
|
/* Decompress a some data from memory to memory, synchronously.
|
|
|
|
$:compBuf pointer to compressed data
|
|
$:compBufSize number of compressed bytes available (must be greater or equal to the number consumed)
|
|
$:rawBuf pointer to output uncompressed data into
|
|
$:rawLen number of uncompressed bytes to output
|
|
$:fuzzSafe (optional) should the decode fail if it contains non-fuzz safe codecs?
|
|
$:checkCRC (optional) if data could be corrupted and you want to know about it, pass OodleLZ_CheckCRC_Yes
|
|
$:verbosity (optional) if not OodleLZ_Verbosity_None, logs some info
|
|
$:decBufBase (optional) if not NULL, provides preceding data to prime the dictionary; must be contiguous with rawBuf, the data between the pointers _dictionaryBase_ and _rawBuf_ is used as the preconditioning data. The exact same precondition must be passed to encoder and decoder. The decBufBase must be a reset point.
|
|
$:decBufSize (optional) size of decode buffer starting at decBufBase, if 0, _rawLen_ is assumed
|
|
$:fpCallback (optional) OodleDecompressCallback to call incrementally as decode proceeds
|
|
$:callbackUserData (optional) passed as userData to fpCallback
|
|
$:decoderMemory (optional) pre-allocated memory for the Decoder, of size _decoderMemorySize_
|
|
$:decoderMemorySize (optional) size of the buffer at _decoderMemory_; must be at least $OodleLZDecoder_MemorySizeNeeded bytes to be used
|
|
$:threadPhase (optional) for threaded decode; see $OodleLZ_About_ThreadPhasedDecode (default OodleLZ_Decode_Unthreaded)
|
|
$:return the number of decompressed bytes output, $OODLELZ_FAILED (0) if none can be decompressed
|
|
|
|
Decodes data encoded with any $OodleLZ_Compressor.
|
|
|
|
Note : _rawLen_ must be the actual number of bytes to output, the same as the number that were encoded with the corresponding
|
|
OodleLZ_Compress size. You must store this somewhere in your own header and pass it in to this call. _compBufSize_ does NOT
|
|
need to be the exact number of compressed bytes, is the number of bytes available in the buffer, it must be greater or equal to
|
|
the actual compressed length.
|
|
|
|
Note that the new compressors (Kraken,Mermaid,Selkie,BitKnit) are all fuzz safe and you can use OodleLZ_FuzzSafe_Yes
|
|
with them and no padding of the decode target buffer.
|
|
|
|
If checkCRC is OodleLZ_CheckCRC_Yes, then corrupt data will be detected and the decode aborted.
|
|
|
|
If checkCRC is OodleLZ_CheckCRC_No, then corruption might result in invalid data, but no detection of any error (garbage in, garbage out).
|
|
|
|
If corruption is possible, _fuzzSafe_ is No and _checkCRC_ is OodleLZ_CheckCRC_No, $OodleLZ_GetDecodeBufferSize must be used to allocate
|
|
_rawBuf_ large enough to prevent overrun.
|
|
|
|
$OodleLZ_GetDecodeBufferSize should always be used to ensure _rawBuf_ is large enough, even when corruption is not
|
|
possible (when fuzzSafe is No).
|
|
|
|
_compBuf_ and _rawBuf_ are allowed to overlap for "in place" decoding, but then _rawBuf_ must be allocated to
|
|
the size given by $OodleLZ_GetInPlaceDecodeBufferSize , and the compressed data must be at the end of that buffer.
|
|
|
|
An easy way to take the next step to parallel decoding is with $OodleXLZ_Decompress_MakeSeekTable_Wide_Async (in the Oodle2 Ext lib)
|
|
|
|
NOTE : the return value is the *total* number of decompressed bytes output so far. If rawBuf is > decBufBase, that means
|
|
the initial inset of (rawBuf - decBufBase) is included! (eg. you won't just get _rawLen_)
|
|
|
|
If _decBufBase_ is provided, the backup distance from _rawBuf_ must be a multiple of $OODLELZ_BLOCK_LEN
|
|
|
|
About fuzz safety:
|
|
|
|
OodleLZ_Decompress is guaranteed not to crash even if the data is corrupted when _fuzzSafe_ is set to OodleLZ_FuzzSafe_Yes.
|
|
|
|
When _fuzzSafe_ is Yes, the target buffer (_rawBuf_ and _rawLen_) will never be overrun. Note that corrupted data might not
|
|
be detected (the return value might indicate success).
|
|
|
|
Fuzz Safe decodes will not crash on corrupt data. They may or may not return failure, and produce garbage output.
|
|
|
|
Fuzz safe decodes will not read out of bounds. They won't put data on the stack or previously in memory
|
|
into the output buffer.
|
|
|
|
Fuzz safe decodes will not output more than the uncompressed size. (eg. the output buffer does not need to
|
|
be padded like OodleLZ_GetDecodeBufferSize)
|
|
|
|
If you ask for a fuzz safe decode and the compressor doesn't satisfy OodleLZ_Compressor_CanDecodeFuzzSafe
|
|
then it will return failure.
|
|
|
|
The _fuzzSafe_ argument should always be OodleLZ_FuzzSafe_Yes as of Oodle 2.9.0 ; older compressors did not
|
|
support fuzz safety but they now all do.
|
|
|
|
Use of OodleLZ_FuzzSafe_No is deprecated.
|
|
|
|
*/
|
|
int OodleLZ_Decompress(
|
|
const void* compressed_buffer,
|
|
size_t compressed_length,
|
|
void* raw_buffer,
|
|
size_t raw_length,
|
|
OodleLZ_FuzzSafe fuzz_safe, // Default: OodleLZ_FuzzSafe_Yes
|
|
OodleLZ_CheckCRC check_crc, // Default: OodleLZ_CheckCRC_No
|
|
OodleLZ_Verbosity verbosity, // Default: OodleLZ_Verbosity_None
|
|
void* decBufBase, // Default: null
|
|
size_t decBufSize, // Default: 0
|
|
void* callback, // Default: null
|
|
void* callback_user_data, // Default: null
|
|
void* decoder_memory, // Default: null
|
|
size_t decoder_memory_size, // Default: 0
|
|
OodleLZ_Decode_ThreadPhase thread_phase // Default: OodleLZ_Decode_Unthreaded
|
|
);
|