Rizin
unix-like reverse engineering framework and cli tools
lz4frame.h File Reference
#include <stddef.h>

Go to the source code of this file.

Classes

struct  LZ4F_frameInfo_t
 
struct  LZ4F_preferences_t
 
struct  LZ4F_compressOptions_t
 
struct  LZ4F_decompressOptions_t
 

Macros

#define LZ4FLIB_VISIBILITY
 
#define LZ4FLIB_API   LZ4FLIB_VISIBILITY
 
#define LZ4F_DEPRECATE(x)   x /* no deprecation warning for this compiler */
 
#define LZ4F_OBSOLETE_ENUM(x)
 
#define LZ4F_INIT_FRAMEINFO   { LZ4F_default, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */
 
#define LZ4F_INIT_PREFERENCES   { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */
 
#define LZ4F_VERSION   100 /* This number can be used to check for an incompatible API breaking change */
 
#define LZ4F_HEADER_SIZE_MIN   7 /* LZ4 Frame header size can vary, depending on selected paramaters */
 
#define LZ4F_HEADER_SIZE_MAX   19
 
#define LZ4F_BLOCK_HEADER_SIZE   4
 
#define LZ4F_BLOCK_CHECKSUM_SIZE   4
 
#define LZ4F_CONTENT_CHECKSUM_SIZE   4
 
#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH   5
 

Typedefs

typedef size_t LZ4F_errorCode_t
 
typedef struct LZ4F_cctx_s LZ4F_cctx
 
typedef LZ4F_cctxLZ4F_compressionContext_t
 
typedef struct LZ4F_dctx_s LZ4F_dctx
 
typedef LZ4F_dctxLZ4F_decompressionContext_t
 

Enumerations

enum  LZ4F_blockSizeID_t {
  LZ4F_default =0 , LZ4F_max64KB =4 , LZ4F_max256KB =5 , LZ4F_max1MB =6 ,
  LZ4F_max4MB =7
}
 
enum  LZ4F_blockMode_t { LZ4F_blockLinked =0 , LZ4F_blockIndependent }
 
enum  LZ4F_contentChecksum_t { LZ4F_noContentChecksum =0 , LZ4F_contentChecksumEnabled }
 
enum  LZ4F_blockChecksum_t { LZ4F_noBlockChecksum =0 , LZ4F_blockChecksumEnabled }
 
enum  LZ4F_frameType_t { LZ4F_frame =0 , LZ4F_skippableFrame }
 

Functions

LZ4FLIB_API unsigned LZ4F_isError (LZ4F_errorCode_t code)
 
LZ4FLIB_API const char * LZ4F_getErrorName (LZ4F_errorCode_t code)
 
LZ4FLIB_API int LZ4F_compressionLevel_max (void)
 
LZ4FLIB_API size_t LZ4F_compressFrameBound (size_t srcSize, const LZ4F_preferences_t *preferencesPtr)
 
LZ4FLIB_API size_t LZ4F_compressFrame (void *dstBuffer, size_t dstCapacity, const void *srcBuffer, size_t srcSize, const LZ4F_preferences_t *preferencesPtr)
 
LZ4FLIB_API unsigned LZ4F_getVersion (void)
 
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext (LZ4F_cctx **cctxPtr, unsigned version)
 
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext (LZ4F_cctx *cctx)
 
LZ4FLIB_API size_t LZ4F_compressBegin (LZ4F_cctx *cctx, void *dstBuffer, size_t dstCapacity, const LZ4F_preferences_t *prefsPtr)
 
LZ4FLIB_API size_t LZ4F_compressBound (size_t srcSize, const LZ4F_preferences_t *prefsPtr)
 
LZ4FLIB_API size_t LZ4F_compressUpdate (LZ4F_cctx *cctx, void *dstBuffer, size_t dstCapacity, const void *srcBuffer, size_t srcSize, const LZ4F_compressOptions_t *cOptPtr)
 
LZ4FLIB_API size_t LZ4F_flush (LZ4F_cctx *cctx, void *dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t *cOptPtr)
 
LZ4FLIB_API size_t LZ4F_compressEnd (LZ4F_cctx *cctx, void *dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t *cOptPtr)
 
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext (LZ4F_dctx **dctxPtr, unsigned version)
 
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext (LZ4F_dctx *dctx)
 
LZ4FLIB_API size_t LZ4F_headerSize (const void *src, size_t srcSize)
 
LZ4FLIB_API size_t LZ4F_getFrameInfo (LZ4F_dctx *dctx, LZ4F_frameInfo_t *frameInfoPtr, const void *srcBuffer, size_t *srcSizePtr)
 
LZ4FLIB_API size_t LZ4F_decompress (LZ4F_dctx *dctx, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, const LZ4F_decompressOptions_t *dOptPtr)
 
LZ4FLIB_API void LZ4F_resetDecompressionContext (LZ4F_dctx *dctx)
 

Macro Definition Documentation

◆ LZ4F_BLOCK_CHECKSUM_SIZE

#define LZ4F_BLOCK_CHECKSUM_SIZE   4

Definition at line 266 of file lz4frame.h.

◆ LZ4F_BLOCK_HEADER_SIZE

#define LZ4F_BLOCK_HEADER_SIZE   4

Definition at line 263 of file lz4frame.h.

◆ LZ4F_CONTENT_CHECKSUM_SIZE

#define LZ4F_CONTENT_CHECKSUM_SIZE   4

Definition at line 269 of file lz4frame.h.

◆ LZ4F_DEPRECATE

#define LZ4F_DEPRECATE (   x)    x /* no deprecation warning for this compiler */

Definition at line 95 of file lz4frame.h.

◆ LZ4F_HEADER_SIZE_MAX

#define LZ4F_HEADER_SIZE_MAX   19

Definition at line 260 of file lz4frame.h.

◆ LZ4F_HEADER_SIZE_MIN

#define LZ4F_HEADER_SIZE_MIN   7 /* LZ4 Frame header size can vary, depending on selected paramaters */

Definition at line 259 of file lz4frame.h.

◆ LZ4F_INIT_FRAMEINFO

#define LZ4F_INIT_FRAMEINFO   { LZ4F_default, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */

Definition at line 185 of file lz4frame.h.

◆ LZ4F_INIT_PREFERENCES

#define LZ4F_INIT_PREFERENCES   { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */

Definition at line 200 of file lz4frame.h.

◆ LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH

#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH   5

Definition at line 374 of file lz4frame.h.

◆ LZ4F_OBSOLETE_ENUM

#define LZ4F_OBSOLETE_ENUM (   x)

Definition at line 116 of file lz4frame.h.

◆ LZ4F_VERSION

#define LZ4F_VERSION   100 /* This number can be used to check for an incompatible API breaking change */

Definition at line 242 of file lz4frame.h.

◆ LZ4FLIB_API

#define LZ4FLIB_API   LZ4FLIB_VISIBILITY

Definition at line 84 of file lz4frame.h.

◆ LZ4FLIB_VISIBILITY

#define LZ4FLIB_VISIBILITY

Introduction

lz4frame.h implements LZ4 frame specification (doc/lz4_Frame_format.md). lz4frame.h provides frame compression functions that take care of encoding standard metadata alongside LZ4-compressed blocks.

Definition at line 76 of file lz4frame.h.

Typedef Documentation

◆ LZ4F_cctx

typedef struct LZ4F_cctx_s LZ4F_cctx

Definition at line 224 of file lz4frame.h.

◆ LZ4F_compressionContext_t

Definition at line 233 of file lz4frame.h.

◆ LZ4F_dctx

typedef struct LZ4F_dctx_s LZ4F_dctx

Definition at line 338 of file lz4frame.h.

◆ LZ4F_decompressionContext_t

Definition at line 347 of file lz4frame.h.

◆ LZ4F_errorCode_t

Definition at line 103 of file lz4frame.h.

Enumeration Type Documentation

◆ LZ4F_blockChecksum_t

Enumerator
LZ4F_noBlockChecksum 
LZ4F_blockChecksumEnabled 

Definition at line 152 of file lz4frame.h.

152  {
LZ4F_blockChecksum_t
Definition: lz4frame.h:152
@ LZ4F_blockChecksumEnabled
Definition: lz4frame.h:154
@ LZ4F_noBlockChecksum
Definition: lz4frame.h:153

◆ LZ4F_blockMode_t

Enumerator
LZ4F_blockLinked 
LZ4F_blockIndependent 

Definition at line 138 of file lz4frame.h.

138  {
141  LZ4F_OBSOLETE_ENUM(blockLinked)
142  LZ4F_OBSOLETE_ENUM(blockIndependent)
LZ4F_blockMode_t
Definition: lz4frame.h:138
@ LZ4F_blockLinked
Definition: lz4frame.h:139
@ LZ4F_blockIndependent
Definition: lz4frame.h:140
#define LZ4F_OBSOLETE_ENUM(x)
Definition: lz4frame.h:116

◆ LZ4F_blockSizeID_t

Enumerator
LZ4F_default 
LZ4F_max64KB 
LZ4F_max256KB 
LZ4F_max1MB 
LZ4F_max4MB 

Definition at line 123 of file lz4frame.h.

123  {
124  LZ4F_default=0,
125  LZ4F_max64KB=4,
126  LZ4F_max256KB=5,
127  LZ4F_max1MB=6,
128  LZ4F_max4MB=7
129  LZ4F_OBSOLETE_ENUM(max64KB)
130  LZ4F_OBSOLETE_ENUM(max256KB)
131  LZ4F_OBSOLETE_ENUM(max1MB)
132  LZ4F_OBSOLETE_ENUM(max4MB)
LZ4F_blockSizeID_t
Definition: lz4frame.h:123
@ LZ4F_max256KB
Definition: lz4frame.h:126
@ LZ4F_default
Definition: lz4frame.h:124
@ LZ4F_max1MB
Definition: lz4frame.h:127
@ LZ4F_max64KB
Definition: lz4frame.h:125
@ LZ4F_max4MB
Definition: lz4frame.h:128

◆ LZ4F_contentChecksum_t

Enumerator
LZ4F_noContentChecksum 
LZ4F_contentChecksumEnabled 

Definition at line 145 of file lz4frame.h.

145  {
148  LZ4F_OBSOLETE_ENUM(noContentChecksum)
149  LZ4F_OBSOLETE_ENUM(contentChecksumEnabled)
LZ4F_contentChecksum_t
Definition: lz4frame.h:145
@ LZ4F_noContentChecksum
Definition: lz4frame.h:146
@ LZ4F_contentChecksumEnabled
Definition: lz4frame.h:147

◆ LZ4F_frameType_t

Enumerator
LZ4F_frame 
LZ4F_skippableFrame 

Definition at line 157 of file lz4frame.h.

157  {
158  LZ4F_frame=0,
LZ4F_frameType_t
Definition: lz4frame.h:157
@ LZ4F_skippableFrame
Definition: lz4frame.h:159
@ LZ4F_frame
Definition: lz4frame.h:158
@ skippableFrame
Definition: lz4io.c:1361

Function Documentation

◆ LZ4F_compressBegin()

LZ4FLIB_API size_t LZ4F_compressBegin ( LZ4F_cctx cctxPtr,
void *  dstBuffer,
size_t  dstCapacity,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressBegin() : will write the frame header into dstBuffer. dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to default.

Returns
: number of bytes written into dstBuffer for the header or an error code (which can be tested using LZ4F_isError())

LZ4F_compressBegin() : init streaming compression and writes frame header into dstBuffer. dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes. preferencesPtr can be NULL, in which case default parameters are selected.

Returns
: number of bytes written into dstBuffer for the header or an error code (can be tested using LZ4F_isError())

Definition at line 710 of file lz4frame.c.

713 {
714  return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity,
715  NULL, preferencesPtr);
716 }
#define NULL
Definition: cris-opc.c:27
size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstCapacity, const LZ4F_CDict *cdict, const LZ4F_preferences_t *preferencesPtr)
Definition: lz4frame.c:598

References LZ4F_compressBegin_usingCDict(), and NULL.

Referenced by basicTests(), compress_file_internal(), and fuzzerTests().

◆ LZ4F_compressBound()

LZ4FLIB_API size_t LZ4F_compressBound ( size_t  srcSize,
const LZ4F_preferences_t prefsPtr 
)

LZ4F_compressBound() : Provides minimum dstCapacity required to guarantee success of LZ4F_compressUpdate(), given a srcSize and preferences, for a worst case scenario. When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() instead. Note that the result is only valid for a single invocation of LZ4F_compressUpdate(). When invoking LZ4F_compressUpdate() multiple times, if the output buffer is gradually filled up instead of emptied and re-used from its start, one must check if there is enough remaining capacity before each invocation, using LZ4F_compressBound().

Returns
is always the same for a srcSize and prefsPtr. prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario. tech details :
if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes. It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd().
doesn't include frame header, as it was already generated by LZ4F_compressBegin().

Definition at line 724 of file lz4frame.c.

725 {
726  if (preferencesPtr && preferencesPtr->autoFlush) {
727  return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0);
728  }
729  return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);
730 }
char int srcSize
Definition: lz4.h:697
static size_t LZ4F_compressBound_internal(size_t srcSize, const LZ4F_preferences_t *preferencesPtr, size_t alreadyBuffered)
Definition: lz4frame.c:324

References LZ4F_preferences_t::autoFlush, LZ4F_compressBound_internal(), and srcSize.

Referenced by basicTests(), compress_file(), compress_file_internal(), and fuzzerTests().

◆ LZ4F_compressEnd()

LZ4FLIB_API size_t LZ4F_compressEnd ( LZ4F_cctx cctxPtr,
void *  dstBuffer,
size_t  dstCapacity,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_compressEnd() : To properly finish an LZ4 frame, invoke LZ4F_compressEnd(). It will flush whatever data remained within cctx (like LZ4_flush()) and properly finalize the frame, with an endMark and a checksum. cOptPtr is optional : NULL can be provided, in which case all options will be set to default.

Returns
: nb of bytes written into dstBuffer, necessarily >= 4 (endMark), or an error code if it fails (which can be tested using LZ4F_isError()) Note : LZ4F_compressEnd() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr). A successful call to LZ4F_compressEnd() makes cctx available again for another compression task.

LZ4F_compressEnd() : When you want to properly finish the compressed frame, just call LZ4F_compressEnd(). It will flush whatever data remained within compressionContext (like LZ4_flush()) but also properly finalize the frame, with an endMark and an (optional) checksum. LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.

Returns
: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size)) or an error code if it fails (can be tested using LZ4F_isError()) The context can then be used again to compress a new frame, starting with LZ4F_compressBegin().

Definition at line 986 of file lz4frame.c.

989 {
990  BYTE* const dstStart = (BYTE*)dstBuffer;
991  BYTE* dstPtr = dstStart;
992 
993  size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
994  DEBUGLOG(5,"LZ4F_compressEnd: dstCapacity=%u", (unsigned)dstCapacity);
995  if (LZ4F_isError(flushSize)) return flushSize;
996  dstPtr += flushSize;
997 
998  assert(flushSize <= dstCapacity);
999  dstCapacity -= flushSize;
1000 
1001  if (dstCapacity < 4) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
1002  LZ4F_writeLE32(dstPtr, 0);
1003  dstPtr += 4; /* endMark */
1004 
1006  U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
1007  if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
1008  DEBUGLOG(5,"Writing 32-bit content checksum");
1009  LZ4F_writeLE32(dstPtr, xxh);
1010  dstPtr+=4; /* content Checksum */
1011  }
1012 
1013  cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
1014  cctxPtr->maxBufferSize = 0; /* reuse HC context */
1015 
1016  if (cctxPtr->prefs.frameInfo.contentSize) {
1017  if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
1018  return err0r(LZ4F_ERROR_frameSize_wrong);
1019  }
1020 
1021  return (size_t)(dstPtr - dstStart);
1022 }
XXH_PUBLIC_API unsigned int XXH32_digest(const XXH32_state_t *state_in)
Definition: xxhash.c:546
unsigned char BYTE
Definition: lz4.c:286
unsigned int U32
Definition: lz4.c:288
static void LZ4F_writeLE32(void *dst, U32 value32)
Definition: lz4frame.c:157
size_t LZ4F_flush(LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t *compressOptionsPtr)
Definition: lz4frame.c:938
#define DEBUGLOG(l,...)
Definition: lz4frame.c:123
static LZ4F_errorCode_t err0r(LZ4F_errorCodes code)
Definition: lz4frame.c:267
unsigned LZ4F_isError(LZ4F_errorCode_t code)
Definition: lz4frame.c:249
#define assert(condition)
Definition: lz4frame.c:107
U32 cStage
Definition: lz4frame.c:227
U64 totalInSize
Definition: lz4frame.c:234
size_t maxBufferSize
Definition: lz4frame.c:230
LZ4F_preferences_t prefs
Definition: lz4frame.c:225
XXH32_state_t xxh
Definition: lz4frame.c:235
LZ4F_contentChecksum_t contentChecksumFlag
Definition: lz4frame.h:178
unsigned long long contentSize
Definition: lz4frame.h:180
LZ4F_frameInfo_t frameInfo
Definition: lz4frame.h:193

References assert, LZ4F_frameInfo_t::contentChecksumFlag, LZ4F_frameInfo_t::contentSize, LZ4F_cctx_s::cStage, DEBUGLOG, err0r(), LZ4F_preferences_t::frameInfo, LZ4F_contentChecksumEnabled, LZ4F_flush(), LZ4F_isError(), LZ4F_writeLE32(), LZ4F_cctx_s::maxBufferSize, LZ4F_cctx_s::prefs, LZ4F_cctx_s::totalInSize, LZ4F_cctx_s::xxh, and XXH32_digest().

Referenced by basicTests(), compress_file_internal(), fuzzerTests(), LZ4F_compressFrame_usingCDict(), and LZ4IO_compressFilename_extRess().

◆ LZ4F_compressFrame()

LZ4FLIB_API size_t LZ4F_compressFrame ( void *  dstBuffer,
size_t  dstCapacity,
const void *  srcBuffer,
size_t  srcSize,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressFrame() : Compress an entire srcBuffer into a valid LZ4 frame. dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.

Returns
: number of bytes written into dstBuffer. or an error code if it fails (can be tested using LZ4F_isError())

LZ4F_compressFrame() : Compress an entire srcBuffer into a valid LZ4 frame, in a single step. dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.

Returns
: number of bytes written into dstBuffer. or an error code if it fails (can be tested using LZ4F_isError())

Definition at line 429 of file lz4frame.c.

432 {
433  size_t result;
434 #if (LZ4F_HEAPMODE)
435  LZ4F_cctx_t *cctxPtr;
436  result = LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION);
437  if (LZ4F_isError(result)) return result;
438 #else
439  LZ4F_cctx_t cctx;
440  LZ4_stream_t lz4ctx;
441  LZ4F_cctx_t *cctxPtr = &cctx;
442 
443  DEBUGLOG(4, "LZ4F_compressFrame");
444  MEM_INIT(&cctx, 0, sizeof(cctx));
445  cctx.version = LZ4F_VERSION;
446  cctx.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */
447  if (preferencesPtr == NULL ||
448  preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN)
449  {
450  LZ4_initStream(&lz4ctx, sizeof(lz4ctx));
451  cctxPtr->lz4CtxPtr = &lz4ctx;
452  cctxPtr->lz4CtxAlloc = 1;
453  cctxPtr->lz4CtxState = 1;
454  }
455 #endif
456 
457  result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity,
458  srcBuffer, srcSize,
459  NULL, preferencesPtr);
460 
461 #if (LZ4F_HEAPMODE)
463 #else
464  if (preferencesPtr != NULL &&
465  preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN)
466  {
467  FREEMEM(cctxPtr->lz4CtxPtr);
468  }
469 #endif
470  return result;
471 }
LZ4_stream_t * LZ4_initStream(void *buffer, size_t size)
Definition: lz4.c:1443
size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx *cctx, void *dstBuffer, size_t dstCapacity, const void *srcBuffer, size_t srcSize, const LZ4F_CDict *cdict, const LZ4F_preferences_t *preferencesPtr)
Definition: lz4frame.c:373
LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx *cctxPtr)
Definition: lz4frame.c:550
#define FREEMEM(p)
Definition: lz4frame.c:78
#define MEM_INIT(p, v, s)
Definition: lz4frame.c:83
LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx **LZ4F_compressionContextPtr, unsigned version)
Definition: lz4frame.c:536
#define LZ4F_VERSION
Definition: lz4frame.h:242
#define LZ4HC_CLEVEL_MIN
Definition: lz4hc.h:47
U16 lz4CtxState
Definition: lz4frame.c:238
U16 lz4CtxAlloc
Definition: lz4frame.c:237
U32 version
Definition: lz4frame.c:226
void * lz4CtxPtr
Definition: lz4frame.c:236
#define MB
Definition: unum.c:92

References LZ4F_preferences_t::compressionLevel, DEBUGLOG, FREEMEM, LZ4_initStream(), LZ4F_cctx_s::lz4CtxAlloc, LZ4F_cctx_s::lz4CtxPtr, LZ4F_cctx_s::lz4CtxState, LZ4F_compressFrame_usingCDict(), LZ4F_createCompressionContext(), LZ4F_freeCompressionContext(), LZ4F_isError(), LZ4F_VERSION, LZ4HC_CLEVEL_MIN, LZ4F_cctx_s::maxBufferSize, MB, MEM_INIT, NULL, srcSize, and LZ4F_cctx_s::version.

Referenced by basicTests(), fullSpeedBench(), fuzzerTests(), LLVMFuzzerTestOneInput(), and local_LZ4F_compressFrame().

◆ LZ4F_compressFrameBound()

LZ4FLIB_API size_t LZ4F_compressFrameBound ( size_t  srcSize,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressFrameBound() : Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences. preferencesPtr is optional. It can be replaced by NULL, in which case, the function will assume default preferences. Note : this result is only usable with LZ4F_compressFrame(). It may also be used with LZ4F_compressUpdate() if no flush() operation is performed.

Definition at line 351 of file lz4frame.c.

352 {
353  LZ4F_preferences_t prefs;
354  size_t const headerSize = maxFHSize; /* max header size, including optional fields */
355 
356  if (preferencesPtr!=NULL) prefs = *preferencesPtr;
357  else MEM_INIT(&prefs, 0, sizeof(prefs));
358  prefs.autoFlush = 1;
359 
360  return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);;
361 }
static const size_t maxFHSize
Definition: lz4frame.c:215
unsigned autoFlush
Definition: lz4frame.h:195

References LZ4F_preferences_t::autoFlush, LZ4F_compressBound_internal(), maxFHSize, MEM_INIT, NULL, and srcSize.

Referenced by basicTests(), fuzzerTests(), LLVMFuzzerTestOneInput(), local_LZ4F_compressFrame(), LZ4F_compressFrame_usingCDict(), and LZ4IO_createCResources().

◆ LZ4F_compressionLevel_max()

LZ4FLIB_API int LZ4F_compressionLevel_max ( void  )

Definition at line 276 of file lz4frame.c.

276 { return LZ4HC_CLEVEL_MAX; }
#define LZ4HC_CLEVEL_MAX
Definition: lz4hc.h:50

References LZ4HC_CLEVEL_MAX.

Referenced by basicTests().

◆ LZ4F_compressUpdate()

LZ4FLIB_API size_t LZ4F_compressUpdate ( LZ4F_cctx cctxPtr,
void *  dstBuffer,
size_t  dstCapacity,
const void *  srcBuffer,
size_t  srcSize,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_compressUpdate() : LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. Important rule: dstCapacity MUST be large enough to ensure operation success even in worst case situations. This value is provided by LZ4F_compressBound(). If this condition is not respected, LZ4F_compress() will fail (result is an errorCode). LZ4F_compressUpdate() doesn't guarantee error recovery. When an error occurs, compression context must be freed or resized. cOptPtr is optional : NULL can be provided, in which case all options are set to default.

Returns
: number of bytes written into dstBuffer (it can be zero, meaning input data was just buffered). or an error code if it fails (which can be tested using LZ4F_isError())

LZ4F_compressUpdate() : LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. dstBuffer MUST be >= LZ4F_compressBound(srcSize, preferencesPtr). LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.

Returns
: the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered. or an error code if it fails (which can be tested using LZ4F_isError())

Definition at line 825 of file lz4frame.c.

829 {
830  LZ4F_compressOptions_t cOptionsNull;
831  size_t const blockSize = cctxPtr->maxBlockSize;
832  const BYTE* srcPtr = (const BYTE*)srcBuffer;
833  const BYTE* const srcEnd = srcPtr + srcSize;
834  BYTE* const dstStart = (BYTE*)dstBuffer;
835  BYTE* dstPtr = dstStart;
836  LZ4F_lastBlockStatus lastBlockCompressed = notDone;
838 
839  DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize);
840 
841  if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
842  if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
843  return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
844  MEM_INIT(&cOptionsNull, 0, sizeof(cOptionsNull));
845  if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
846 
847  /* complete tmp buffer */
848  if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
849  size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
850  if (sizeToCopy > srcSize) {
851  /* add src to tmpIn buffer */
852  memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
853  srcPtr = srcEnd;
854  cctxPtr->tmpInSize += srcSize;
855  /* still needs some CRC */
856  } else {
857  /* complete tmpIn block and then compress it */
858  lastBlockCompressed = fromTmpBuffer;
859  memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
860  srcPtr += sizeToCopy;
861 
862  dstPtr += LZ4F_makeBlock(dstPtr,
863  cctxPtr->tmpIn, blockSize,
864  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
865  cctxPtr->cdict,
867 
868  if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
869  cctxPtr->tmpInSize = 0;
870  }
871  }
872 
873  while ((size_t)(srcEnd - srcPtr) >= blockSize) {
874  /* compress full blocks */
875  lastBlockCompressed = fromSrcBuffer;
876  dstPtr += LZ4F_makeBlock(dstPtr,
877  srcPtr, blockSize,
878  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
879  cctxPtr->cdict,
881  srcPtr += blockSize;
882  }
883 
884  if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
885  /* compress remaining input < blockSize */
886  lastBlockCompressed = fromSrcBuffer;
887  dstPtr += LZ4F_makeBlock(dstPtr,
888  srcPtr, (size_t)(srcEnd - srcPtr),
889  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
890  cctxPtr->cdict,
892  srcPtr = srcEnd;
893  }
894 
895  /* preserve dictionary if necessary */
896  if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {
897  if (compressOptionsPtr->stableSrc) {
898  cctxPtr->tmpIn = cctxPtr->tmpBuff;
899  } else {
900  int const realDictSize = LZ4F_localSaveDict(cctxPtr);
901  if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC);
902  cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
903  }
904  }
905 
906  /* keep tmpIn within limits */
907  if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */
908  && !(cctxPtr->prefs.autoFlush))
909  {
910  int const realDictSize = LZ4F_localSaveDict(cctxPtr);
911  cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
912  }
913 
914  /* some input data left, necessarily < blockSize */
915  if (srcPtr < srcEnd) {
916  /* fill tmp buffer */
917  size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
918  memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
919  cctxPtr->tmpInSize = sizeToCopy;
920  }
921 
923  (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
924 
925  cctxPtr->totalInSize += srcSize;
926  return (size_t)(dstPtr - dstStart);
927 }
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: compress.c:68
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *state_in, const void *input, size_t len)
Definition: xxhash.c:515
static size_t LZ4F_makeBlock(void *dst, const void *src, size_t srcSize, compressFunc_t compress, void *lz4ctx, int level, const LZ4F_CDict *cdict, LZ4F_blockChecksum_t crcFlag)
Definition: lz4frame.c:740
static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level)
Definition: lz4frame.c:799
static int LZ4F_localSaveDict(LZ4F_cctx_t *cctxPtr)
Definition: lz4frame.c:809
LZ4F_lastBlockStatus
Definition: lz4frame.c:816
@ fromSrcBuffer
Definition: lz4frame.c:816
@ notDone
Definition: lz4frame.c:816
@ fromTmpBuffer
Definition: lz4frame.c:816
int(* compressFunc_t)(void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level, const LZ4F_CDict *cdict)
Definition: lz4frame.c:733
int size_t
Definition: sftypes.h:40
BYTE * tmpBuff
Definition: lz4frame.c:231
size_t tmpInSize
Definition: lz4frame.c:233
const LZ4F_CDict * cdict
Definition: lz4frame.c:228
size_t maxBlockSize
Definition: lz4frame.c:229
BYTE * tmpIn
Definition: lz4frame.c:232
LZ4F_blockChecksum_t blockChecksumFlag
Definition: lz4frame.h:182
LZ4F_blockMode_t blockMode
Definition: lz4frame.h:177

References LZ4F_preferences_t::autoFlush, LZ4F_frameInfo_t::blockChecksumFlag, LZ4F_frameInfo_t::blockMode, LZ4F_cctx_s::cdict, compress(), LZ4F_preferences_t::compressionLevel, LZ4F_frameInfo_t::contentChecksumFlag, LZ4F_cctx_s::cStage, DEBUGLOG, err0r(), LZ4F_preferences_t::frameInfo, fromSrcBuffer, fromTmpBuffer, LZ4F_cctx_s::lz4CtxPtr, LZ4F_blockLinked, LZ4F_compressBound_internal(), LZ4F_contentChecksumEnabled, LZ4F_localSaveDict(), LZ4F_makeBlock(), LZ4F_selectCompression(), LZ4F_cctx_s::maxBlockSize, LZ4F_cctx_s::maxBufferSize, MEM_INIT, memcpy(), notDone, NULL, LZ4F_cctx_s::prefs, srcSize, LZ4F_compressOptions_t::stableSrc, LZ4F_cctx_s::tmpBuff, LZ4F_cctx_s::tmpIn, LZ4F_cctx_s::tmpInSize, LZ4F_cctx_s::totalInSize, LZ4F_cctx_s::xxh, and XXH32_update().

Referenced by basicTests(), compress_file_internal(), fuzzerTests(), LZ4F_compressFrame_usingCDict(), and LZ4IO_compressFilename_extRess().

◆ LZ4F_createCompressionContext()

LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext ( LZ4F_cctx **  LZ4F_compressionContextPtr,
unsigned  version 
)

LZ4F_createCompressionContext() : The first thing to do is to create a compressionContext object, which will be used in all compression operations. This is achieved using LZ4F_createCompressionContext(), which takes as argument a version. The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL. The function will provide a pointer to a fully allocated LZ4F_cctx object. If

Returns
!= zero, there was an error during context creation. Object can release its memory using LZ4F_freeCompressionContext();

LZ4F_createCompressionContext() : The first thing to do is to create a compressionContext object, which will be used in all compression operations. This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure. The version provided MUST be LZ4F_VERSION. It is intended to track potential incompatible differences between different binaries. The function will provide a pointer to an allocated LZ4F_compressionContext_t object. If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation. Object can release its memory using LZ4F_freeCompressionContext();

Definition at line 536 of file lz4frame.c.

537 {
538  LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t));
539  if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
540 
541  cctxPtr->version = version;
542  cctxPtr->cStage = 0; /* Next stage : init stream */
543 
544  *LZ4F_compressionContextPtr = cctxPtr;
545 
546  return LZ4F_OK_NoError;
547 }
static char * version
Definition: acr.h:4
#define ALLOC_AND_ZERO(s)
Definition: lz4frame.c:77

References ALLOC_AND_ZERO, LZ4F_cctx_s::cStage, err0r(), NULL, LZ4F_cctx_s::version, and version.

Referenced by basicTests(), compress_file(), fuzzerTests(), LZ4F_compressFrame(), and LZ4IO_createCResources().

◆ LZ4F_createDecompressionContext()

LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext ( LZ4F_dctx **  LZ4F_decompressionContextPtr,
unsigned  versionNumber 
)

LZ4F_createDecompressionContext() : Create an LZ4F_dctx object, to track all decompression operations. The version provided MUST be LZ4F_VERSION. The function provides a pointer to an allocated and initialized LZ4F_dctx object. The result is an errorCode, which can be tested using LZ4F_isError(). dctx memory can be released using LZ4F_freeDecompressionContext(); Result of LZ4F_freeDecompressionContext() indicates current state of decompressionContext when being released. That is, it should be == 0 if decompression has been completed fully and correctly.

LZ4F_createDecompressionContext() : Create a decompressionContext object, which will track all decompression operations. Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object. Object can later be released using LZ4F_freeDecompressionContext().

Returns
: if != 0, there was an error during context creation.

Definition at line 1069 of file lz4frame.c.

1070 {
1071  LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOC_AND_ZERO(sizeof(LZ4F_dctx));
1072  if (dctx == NULL) { /* failed allocation */
1073  *LZ4F_decompressionContextPtr = NULL;
1074  return err0r(LZ4F_ERROR_allocation_failed);
1075  }
1076 
1077  dctx->version = versionNumber;
1078  *LZ4F_decompressionContextPtr = dctx;
1079  return LZ4F_OK_NoError;
1080 }

References ALLOC_AND_ZERO, err0r(), NULL, and LZ4F_dctx_s::version.

Referenced by basicTests(), createCResources(), decompress_file(), fullSpeedBench(), FUZZ_decompressFrame(), fuzzerTests(), LLVMFuzzerTestOneInput(), LZ4IO_createDResources(), and LZ4IO_getCompressedFileInfo().

◆ LZ4F_decompress()

LZ4FLIB_API size_t LZ4F_decompress ( LZ4F_dctx dctx,
void *  dstBuffer,
size_t dstSizePtr,
const void *  srcBuffer,
size_t srcSizePtr,
const LZ4F_decompressOptions_t decompressOptionsPtr 
)

LZ4F_decompress() : Call this function repetitively to regenerate data compressed in srcBuffer.

The function requires a valid dctx state. It will read up to *srcSizePtr bytes from srcBuffer, and decompress data into dstBuffer, of capacity *dstSizePtr.

The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value). The nb of bytes decompressed into dstBuffer will be written into *dstSizePtr (necessarily <= original value).

The function does not necessarily read all input bytes, so always check value in *srcSizePtr. Unconsumed source data must be presented again in subsequent invocations.

dstBuffer can freely change between each consecutive function invocation. dstBuffer content will be overwritten.

Returns
: an hint of how many srcSize bytes LZ4F_decompress() expects for next call. Schematically, it's the size of the current (or remaining) compressed block + header of next block. Respecting the hint provides some small speed benefit, because it skips intermediate buffers. This is just a hint though, it's always possible to provide any srcSize.

When a frame is fully decoded,

Returns
will be 0 (no more data expected). When provided with more bytes than necessary to decode a frame, LZ4F_decompress() will stop reading exactly at end of current frame, and
0.

If decompression failed,

Returns
is an error code, which can be tested using LZ4F_isError(). After a decompression error, the dctx context is not resumable. Use LZ4F_resetDecompressionContext() to return to clean state.

After a frame is fully decoded, dctx can be used again to decompress another frame.

LZ4F_decompress() : Call this function repetitively to regenerate compressed data in srcBuffer. The function will attempt to decode up to *srcSizePtr bytes from srcBuffer into dstBuffer of capacity *dstSizePtr.

The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).

The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value). If number of bytes read is < number of bytes provided, then decompression operation is not complete. Remaining data will have to be presented again in a subsequent invocation.

The function result is an hint of the better srcSize to use for next call to LZ4F_decompress. Schematically, it's the size of the current (or remaining) compressed block + header of next block. Respecting the hint provides a small boost to performance, since it allows less buffer shuffling. Note that this is just a hint, and it's always possible to any srcSize value. When a frame is fully decoded,

Returns
will be 0. If decompression failed,
is an error code which can be tested using LZ4F_isError().

Definition at line 1384 of file lz4frame.c.

1388 {
1389  LZ4F_decompressOptions_t optionsNull;
1390  const BYTE* const srcStart = (const BYTE*)srcBuffer;
1391  const BYTE* const srcEnd = srcStart + *srcSizePtr;
1392  const BYTE* srcPtr = srcStart;
1393  BYTE* const dstStart = (BYTE*)dstBuffer;
1394  BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL;
1395  BYTE* dstPtr = dstStart;
1396  const BYTE* selectedIn = NULL;
1397  unsigned doAnotherStage = 1;
1398  size_t nextSrcSizeHint = 1;
1399 
1400 
1401  DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u",
1402  srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr);
1403  if (dstBuffer == NULL) assert(*dstSizePtr == 0);
1404  MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
1405  if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
1406  *srcSizePtr = 0;
1407  *dstSizePtr = 0;
1408  assert(dctx != NULL);
1409 
1410  /* behaves as a state machine */
1411 
1412  while (doAnotherStage) {
1413 
1414  switch(dctx->dStage)
1415  {
1416 
1417  case dstage_getFrameHeader:
1418  DEBUGLOG(6, "dstage_getFrameHeader");
1419  if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
1420  size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */
1421  if (LZ4F_isError(hSize)) return hSize;
1422  srcPtr += hSize;
1423  break;
1424  }
1425  dctx->tmpInSize = 0;
1426  if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */
1427  dctx->tmpInTarget = minFHSize; /* minimum size to decode header */
1429  /* fall-through */
1430 
1432  DEBUGLOG(6, "dstage_storeFrameHeader");
1433  { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));
1434  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1435  dctx->tmpInSize += sizeToCopy;
1436  srcPtr += sizeToCopy;
1437  }
1438  if (dctx->tmpInSize < dctx->tmpInTarget) {
1439  nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
1440  doAnotherStage = 0; /* not enough src data, ask for some more */
1441  break;
1442  }
1443  { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
1444  if (LZ4F_isError(hSize)) return hSize;
1445  }
1446  break;
1447 
1448  case dstage_init:
1449  DEBUGLOG(6, "dstage_init");
1450  if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);
1451  /* internal buffers allocation */
1452  { size_t const bufferNeeded = dctx->maxBlockSize
1453  + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0);
1454  if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
1455  dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
1456  FREEMEM(dctx->tmpIn);
1457  dctx->tmpIn = (BYTE*)ALLOC(dctx->maxBlockSize + BFSize /* block checksum */);
1458  if (dctx->tmpIn == NULL)
1459  return err0r(LZ4F_ERROR_allocation_failed);
1460  FREEMEM(dctx->tmpOutBuffer);
1461  dctx->tmpOutBuffer= (BYTE*)ALLOC(bufferNeeded);
1462  if (dctx->tmpOutBuffer== NULL)
1463  return err0r(LZ4F_ERROR_allocation_failed);
1464  dctx->maxBufferSize = bufferNeeded;
1465  } }
1466  dctx->tmpInSize = 0;
1467  dctx->tmpInTarget = 0;
1468  dctx->tmpOut = dctx->tmpOutBuffer;
1469  dctx->tmpOutStart = 0;
1470  dctx->tmpOutSize = 0;
1471 
1472  dctx->dStage = dstage_getBlockHeader;
1473  /* fall-through */
1474 
1475  case dstage_getBlockHeader:
1476  if ((size_t)(srcEnd - srcPtr) >= BHSize) {
1477  selectedIn = srcPtr;
1478  srcPtr += BHSize;
1479  } else {
1480  /* not enough input to read cBlockSize field */
1481  dctx->tmpInSize = 0;
1483  }
1484 
1485  if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */
1487  { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
1488  size_t const wantedData = BHSize - dctx->tmpInSize;
1489  size_t const sizeToCopy = MIN(wantedData, remainingInput);
1490  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1491  srcPtr += sizeToCopy;
1492  dctx->tmpInSize += sizeToCopy;
1493 
1494  if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */
1495  nextSrcSizeHint = BHSize - dctx->tmpInSize;
1496  doAnotherStage = 0;
1497  break;
1498  }
1499  selectedIn = dctx->tmpIn;
1500  } /* if (dctx->dStage == dstage_storeBlockHeader) */
1501 
1502  /* decode block header */
1503  { U32 const blockHeader = LZ4F_readLE32(selectedIn);
1504  size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU;
1505  size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;
1506  if (blockHeader==0) { /* frameEnd signal, no more block */
1507  DEBUGLOG(5, "end of frame");
1508  dctx->dStage = dstage_getSuffix;
1509  break;
1510  }
1511  if (nextCBlockSize > dctx->maxBlockSize) {
1512  return err0r(LZ4F_ERROR_maxBlockSize_invalid);
1513  }
1514  if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
1515  /* next block is uncompressed */
1516  dctx->tmpInTarget = nextCBlockSize;
1517  DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize);
1518  if (dctx->frameInfo.blockChecksumFlag) {
1519  (void)XXH32_reset(&dctx->blockChecksum, 0);
1520  }
1521  dctx->dStage = dstage_copyDirect;
1522  break;
1523  }
1524  /* next block is a compressed block */
1525  dctx->tmpInTarget = nextCBlockSize + crcSize;
1526  dctx->dStage = dstage_getCBlock;
1527  if (dstPtr==dstEnd || srcPtr==srcEnd) {
1528  nextSrcSizeHint = BHSize + nextCBlockSize + crcSize;
1529  doAnotherStage = 0;
1530  }
1531  break;
1532  }
1533 
1534  case dstage_copyDirect: /* uncompressed block */
1535  DEBUGLOG(6, "dstage_copyDirect");
1536  { size_t sizeToCopy;
1537  if (dstPtr == NULL) {
1538  sizeToCopy = 0;
1539  } else {
1540  size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
1541  sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
1542  memcpy(dstPtr, srcPtr, sizeToCopy);
1543  if (dctx->frameInfo.blockChecksumFlag) {
1544  (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
1545  }
1546  if (dctx->frameInfo.contentChecksumFlag)
1547  (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
1548  if (dctx->frameInfo.contentSize)
1549  dctx->frameRemainingSize -= sizeToCopy;
1550 
1551  /* history management (linked blocks only)*/
1552  if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
1553  LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
1554  } }
1555 
1556  srcPtr += sizeToCopy;
1557  dstPtr += sizeToCopy;
1558  if (sizeToCopy == dctx->tmpInTarget) { /* all done */
1559  if (dctx->frameInfo.blockChecksumFlag) {
1560  dctx->tmpInSize = 0;
1562  } else
1563  dctx->dStage = dstage_getBlockHeader; /* new block */
1564  break;
1565  }
1566  dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
1567  }
1568  nextSrcSizeHint = dctx->tmpInTarget +
1569  +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1570  + BHSize /* next header size */;
1571  doAnotherStage = 0;
1572  break;
1573 
1574  /* check block checksum for recently transferred uncompressed block */
1576  DEBUGLOG(6, "dstage_getBlockChecksum");
1577  { const void* crcSrc;
1578  if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {
1579  crcSrc = srcPtr;
1580  srcPtr += 4;
1581  } else {
1582  size_t const stillToCopy = 4 - dctx->tmpInSize;
1583  size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr));
1584  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1585  dctx->tmpInSize += sizeToCopy;
1586  srcPtr += sizeToCopy;
1587  if (dctx->tmpInSize < 4) { /* all input consumed */
1588  doAnotherStage = 0;
1589  break;
1590  }
1591  crcSrc = dctx->header;
1592  }
1593  { U32 const readCRC = LZ4F_readLE32(crcSrc);
1594  U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
1595 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1596  DEBUGLOG(6, "compare block checksum");
1597  if (readCRC != calcCRC) {
1598  DEBUGLOG(4, "incorrect block checksum: %08X != %08X",
1599  readCRC, calcCRC);
1600  return err0r(LZ4F_ERROR_blockChecksum_invalid);
1601  }
1602 #else
1603  (void)readCRC;
1604  (void)calcCRC;
1605 #endif
1606  } }
1607  dctx->dStage = dstage_getBlockHeader; /* new block */
1608  break;
1609 
1610  case dstage_getCBlock:
1611  DEBUGLOG(6, "dstage_getCBlock");
1612  if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
1613  dctx->tmpInSize = 0;
1614  dctx->dStage = dstage_storeCBlock;
1615  break;
1616  }
1617  /* input large enough to read full block directly */
1618  selectedIn = srcPtr;
1619  srcPtr += dctx->tmpInTarget;
1620 
1621  if (0) /* always jump over next block */
1622  case dstage_storeCBlock:
1623  { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
1624  size_t const inputLeft = (size_t)(srcEnd-srcPtr);
1625  size_t const sizeToCopy = MIN(wantedData, inputLeft);
1626  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1627  dctx->tmpInSize += sizeToCopy;
1628  srcPtr += sizeToCopy;
1629  if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */
1630  nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize)
1631  + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
1632  + BHSize /* next header size */;
1633  doAnotherStage = 0;
1634  break;
1635  }
1636  selectedIn = dctx->tmpIn;
1637  }
1638 
1639  /* At this stage, input is large enough to decode a block */
1640  if (dctx->frameInfo.blockChecksumFlag) {
1641  dctx->tmpInTarget -= 4;
1642  assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */
1643  { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);
1644  U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);
1645 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1646  if (readBlockCrc != calcBlockCrc)
1647  return err0r(LZ4F_ERROR_blockChecksum_invalid);
1648 #else
1649  (void)readBlockCrc;
1650  (void)calcBlockCrc;
1651 #endif
1652  } }
1653 
1654  if ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize) {
1655  const char* dict = (const char*)dctx->dict;
1656  size_t dictSize = dctx->dictSize;
1657  int decodedSize;
1658  assert(dstPtr != NULL);
1659  if (dict && dictSize > 1 GB) {
1660  /* the dictSize param is an int, avoid truncation / sign issues */
1661  dict += dictSize - 64 KB;
1662  dictSize = 64 KB;
1663  }
1664  /* enough capacity in `dst` to decompress directly there */
1665  decodedSize = LZ4_decompress_safe_usingDict(
1666  (const char*)selectedIn, (char*)dstPtr,
1667  (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1668  dict, (int)dictSize);
1669  if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
1670  if (dctx->frameInfo.contentChecksumFlag)
1671  XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize);
1672  if (dctx->frameInfo.contentSize)
1673  dctx->frameRemainingSize -= (size_t)decodedSize;
1674 
1675  /* dictionary management */
1676  if (dctx->frameInfo.blockMode==LZ4F_blockLinked) {
1677  LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
1678  }
1679 
1680  dstPtr += decodedSize;
1681  dctx->dStage = dstage_getBlockHeader;
1682  break;
1683  }
1684 
1685  /* not enough place into dst : decode into tmpOut */
1686  /* ensure enough place for tmpOut */
1687  if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
1688  if (dctx->dict == dctx->tmpOutBuffer) {
1689  if (dctx->dictSize > 128 KB) {
1690  memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB);
1691  dctx->dictSize = 64 KB;
1692  }
1693  dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize;
1694  } else { /* dict not within tmp */
1695  size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);
1696  dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;
1697  } }
1698 
1699  /* Decode block */
1700  { const char* dict = (const char*)dctx->dict;
1701  size_t dictSize = dctx->dictSize;
1702  int decodedSize;
1703  if (dict && dictSize > 1 GB) {
1704  /* the dictSize param is an int, avoid truncation / sign issues */
1705  dict += dictSize - 64 KB;
1706  dictSize = 64 KB;
1707  }
1708  decodedSize = LZ4_decompress_safe_usingDict(
1709  (const char*)selectedIn, (char*)dctx->tmpOut,
1710  (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
1711  dict, (int)dictSize);
1712  if (decodedSize < 0) /* decompression failed */
1713  return err0r(LZ4F_ERROR_decompressionFailed);
1714  if (dctx->frameInfo.contentChecksumFlag)
1715  XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize);
1716  if (dctx->frameInfo.contentSize)
1717  dctx->frameRemainingSize -= (size_t)decodedSize;
1718  dctx->tmpOutSize = (size_t)decodedSize;
1719  dctx->tmpOutStart = 0;
1720  dctx->dStage = dstage_flushOut;
1721  }
1722  /* fall-through */
1723 
1724  case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
1725  DEBUGLOG(6, "dstage_flushOut");
1726  if (dstPtr != NULL) {
1727  size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
1728  memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
1729 
1730  /* dictionary management */
1731  if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
1732  LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/);
1733 
1734  dctx->tmpOutStart += sizeToCopy;
1735  dstPtr += sizeToCopy;
1736  }
1737  if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
1738  dctx->dStage = dstage_getBlockHeader; /* get next block */
1739  break;
1740  }
1741  /* could not flush everything : stop there, just request a block header */
1742  doAnotherStage = 0;
1743  nextSrcSizeHint = BHSize;
1744  break;
1745 
1746  case dstage_getSuffix:
1747  if (dctx->frameRemainingSize)
1748  return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
1749  if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */
1750  nextSrcSizeHint = 0;
1752  doAnotherStage = 0;
1753  break;
1754  }
1755  if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
1756  dctx->tmpInSize = 0;
1757  dctx->dStage = dstage_storeSuffix;
1758  } else {
1759  selectedIn = srcPtr;
1760  srcPtr += 4;
1761  }
1762 
1763  if (dctx->dStage == dstage_storeSuffix) /* can be skipped */
1764  case dstage_storeSuffix:
1765  { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
1766  size_t const wantedData = 4 - dctx->tmpInSize;
1767  size_t const sizeToCopy = MIN(wantedData, remainingInput);
1768  memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
1769  srcPtr += sizeToCopy;
1770  dctx->tmpInSize += sizeToCopy;
1771  if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */
1772  nextSrcSizeHint = 4 - dctx->tmpInSize;
1773  doAnotherStage=0;
1774  break;
1775  }
1776  selectedIn = dctx->tmpIn;
1777  } /* if (dctx->dStage == dstage_storeSuffix) */
1778 
1779  /* case dstage_checkSuffix: */ /* no direct entry, avoid initialization risks */
1780  { U32 const readCRC = LZ4F_readLE32(selectedIn);
1781  U32 const resultCRC = XXH32_digest(&(dctx->xxh));
1782 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1783  if (readCRC != resultCRC)
1784  return err0r(LZ4F_ERROR_contentChecksum_invalid);
1785 #else
1786  (void)readCRC;
1787  (void)resultCRC;
1788 #endif
1789  nextSrcSizeHint = 0;
1791  doAnotherStage = 0;
1792  break;
1793  }
1794 
1795  case dstage_getSFrameSize:
1796  if ((srcEnd - srcPtr) >= 4) {
1797  selectedIn = srcPtr;
1798  srcPtr += 4;
1799  } else {
1800  /* not enough input to read cBlockSize field */
1801  dctx->tmpInSize = 4;
1802  dctx->tmpInTarget = 8;
1804  }
1805 
1806  if (dctx->dStage == dstage_storeSFrameSize)
1808  { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
1809  (size_t)(srcEnd - srcPtr) );
1810  memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
1811  srcPtr += sizeToCopy;
1812  dctx->tmpInSize += sizeToCopy;
1813  if (dctx->tmpInSize < dctx->tmpInTarget) {
1814  /* not enough input to get full sBlockSize; wait for more */
1815  nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize;
1816  doAnotherStage = 0;
1817  break;
1818  }
1819  selectedIn = dctx->header + 4;
1820  } /* if (dctx->dStage == dstage_storeSFrameSize) */
1821 
1822  /* case dstage_decodeSFrameSize: */ /* no direct entry */
1823  { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
1824  dctx->frameInfo.contentSize = SFrameSize;
1825  dctx->tmpInTarget = SFrameSize;
1826  dctx->dStage = dstage_skipSkippable;
1827  break;
1828  }
1829 
1830  case dstage_skipSkippable:
1831  { size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr));
1832  srcPtr += skipSize;
1833  dctx->tmpInTarget -= skipSize;
1834  doAnotherStage = 0;
1835  nextSrcSizeHint = dctx->tmpInTarget;
1836  if (nextSrcSizeHint) break; /* still more to skip */
1837  /* frame fully skipped : prepare context for a new frame */
1839  break;
1840  }
1841  } /* switch (dctx->dStage) */
1842  } /* while (doAnotherStage) */
1843 
1844  /* preserve history within tmp whenever necessary */
1845  LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);
1846  if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */
1847  && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */
1848  && (dctx->dict != NULL) /* dictionary exists */
1849  && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */
1850  && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
1851  {
1852  if (dctx->dStage == dstage_flushOut) {
1853  size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
1854  size_t copySize = 64 KB - dctx->tmpOutSize;
1855  const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
1856  if (dctx->tmpOutSize > 64 KB) copySize = 0;
1857  if (copySize > preserveSize) copySize = preserveSize;
1858  assert(dctx->tmpOutBuffer != NULL);
1859 
1860  memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
1861 
1862  dctx->dict = dctx->tmpOutBuffer;
1863  dctx->dictSize = preserveSize + dctx->tmpOutStart;
1864  } else {
1865  const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
1866  size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
1867 
1868  memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
1869 
1870  dctx->dict = dctx->tmpOutBuffer;
1871  dctx->dictSize = newDictSize;
1872  dctx->tmpOut = dctx->tmpOutBuffer + newDictSize;
1873  }
1874  }
1875 
1876  *srcSizePtr = (size_t)(srcPtr - srcStart);
1877  *dstSizePtr = (size_t)(dstPtr - dstStart);
1878  return nextSrcSizeHint;
1879 }
XXH_PUBLIC_API unsigned int XXH32(const void *input, size_t len, unsigned int seed)
Definition: xxhash.c:392
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, unsigned int seed)
Definition: xxhash.c:437
int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxOutputSize, const char *dictStart, int dictSize)
Definition: lz4.c:2404
#define MIN(a, b)
Definition: lz4frame.c:292
@ dstage_skipSkippable
Definition: lz4frame.c:1038
@ dstage_getCBlock
Definition: lz4frame.c:1034
@ dstage_getSuffix
Definition: lz4frame.c:1036
@ dstage_getFrameHeader
Definition: lz4frame.c:1030
@ dstage_getSFrameSize
Definition: lz4frame.c:1037
@ dstage_storeSFrameSize
Definition: lz4frame.c:1037
@ dstage_storeSuffix
Definition: lz4frame.c:1036
@ dstage_getBlockChecksum
Definition: lz4frame.c:1033
@ dstage_init
Definition: lz4frame.c:1031
@ dstage_storeBlockHeader
Definition: lz4frame.c:1032
@ dstage_storeCBlock
Definition: lz4frame.c:1034
@ dstage_storeFrameHeader
Definition: lz4frame.c:1030
@ dstage_copyDirect
Definition: lz4frame.c:1033
@ dstage_flushOut
Definition: lz4frame.c:1035
@ dstage_getBlockHeader
Definition: lz4frame.c:1032
static U32 LZ4F_readLE32(const void *src)
Definition: lz4frame.c:147
static void LZ4F_updateDict(LZ4F_dctx *dctx, const BYTE *dstPtr, size_t dstSize, const BYTE *dstBufferStart, unsigned withinTmp)
Definition: lz4frame.c:1295
static const size_t minFHSize
Definition: lz4frame.c:214
static const size_t BHSize
Definition: lz4frame.c:216
#define LZ4F_BLOCKUNCOMPRESSED_FLAG
Definition: lz4frame.c:211
static size_t LZ4F_decodeHeader(LZ4F_dctx *dctx, const void *src, size_t srcSize)
Definition: lz4frame.c:1113
#define ALLOC(s)
Definition: lz4frame.c:76
void LZ4F_resetDecompressionContext(LZ4F_dctx *dctx)
Definition: lz4frame.c:1097
#define LZ4F_STATIC_ASSERT(c)
Definition: lz4frame.c:111
static const size_t BFSize
Definition: lz4frame.c:217
size_t dictSize
Definition: lz4frame.c:1053
const BYTE * dict
Definition: lz4frame.c:1052
size_t maxBufferSize
Definition: lz4frame.c:1047
size_t maxBlockSize
Definition: lz4frame.c:1046
dStage_t dStage
Definition: lz4frame.c:1044
size_t tmpInSize
Definition: lz4frame.c:1049
BYTE * tmpIn
Definition: lz4frame.c:1048
size_t tmpOutSize
Definition: lz4frame.c:1055
XXH32_state_t blockChecksum
Definition: lz4frame.c:1058
size_t tmpOutStart
Definition: lz4frame.c:1056
BYTE header[LZ4F_HEADER_SIZE_MAX]
Definition: lz4frame.c:1059
LZ4F_frameInfo_t frameInfo
Definition: lz4frame.c:1042
BYTE * tmpOutBuffer
Definition: lz4frame.c:1051
XXH32_state_t xxh
Definition: lz4frame.c:1057
size_t tmpInTarget
Definition: lz4frame.c:1050
BYTE * tmpOut
Definition: lz4frame.c:1054
U64 frameRemainingSize
Definition: lz4frame.c:1045
#define KB
Definition: unum.c:91
#define GB
Definition: unum.c:93
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References ALLOC, assert, BFSize, BHSize, LZ4F_dctx_s::blockChecksum, LZ4F_frameInfo_t::blockChecksumFlag, LZ4F_frameInfo_t::blockMode, LZ4F_frameInfo_t::contentChecksumFlag, LZ4F_frameInfo_t::contentSize, DEBUGLOG, LZ4F_dctx_s::dict, LZ4F_dctx_s::dictSize, LZ4F_dctx_s::dStage, dstage_copyDirect, dstage_flushOut, dstage_getBlockChecksum, dstage_getBlockHeader, dstage_getCBlock, dstage_getFrameHeader, dstage_getSFrameSize, dstage_getSuffix, dstage_init, dstage_skipSkippable, dstage_storeBlockHeader, dstage_storeCBlock, dstage_storeFrameHeader, dstage_storeSFrameSize, dstage_storeSuffix, err0r(), LZ4F_dctx_s::frameInfo, LZ4F_dctx_s::frameRemainingSize, FREEMEM, GB, LZ4F_dctx_s::header, if(), KB, LZ4_decompress_safe_usingDict(), LZ4F_blockLinked, LZ4F_BLOCKUNCOMPRESSED_FLAG, LZ4F_decodeHeader(), LZ4F_isError(), LZ4F_readLE32(), LZ4F_resetDecompressionContext(), LZ4F_STATIC_ASSERT, LZ4F_updateDict(), LZ4F_dctx_s::maxBlockSize, LZ4F_dctx_s::maxBufferSize, maxFHSize, MEM_INIT, memcpy(), MIN, minFHSize, NULL, LZ4F_decompressOptions_t::stableDst, LZ4F_dctx_s::tmpIn, LZ4F_dctx_s::tmpInSize, LZ4F_dctx_s::tmpInTarget, LZ4F_dctx_s::tmpOut, LZ4F_dctx_s::tmpOutBuffer, LZ4F_dctx_s::tmpOutSize, LZ4F_dctx_s::tmpOutStart, LZ4F_dctx_s::xxh, XXH32(), XXH32_digest(), XXH32_reset(), and XXH32_update().

Referenced by basicTests(), decompress(), decompress_file_internal(), frameCheck(), FUZZ_decompressFrame(), local_LZ4F_decompress(), local_LZ4F_decompress_followHint(), local_LZ4F_decompress_noHint(), LZ4F_decompress_usingDict(), LZ4F_getFrameInfo(), and test_lz4f_decompression_wBuffers().

◆ LZ4F_flush()

LZ4FLIB_API size_t LZ4F_flush ( LZ4F_cctx cctxPtr,
void *  dstBuffer,
size_t  dstCapacity,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_flush() : When data must be generated and sent immediately, without waiting for a block to be completely filled, it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx. dstCapacity must be large enough to ensure the operation will be successful. cOptPtr is optional : it's possible to provide NULL, all options will be set to default.

Returns
: nb of bytes written into dstBuffer (can be zero, when there is no data stored within cctx) or an error code if it fails (which can be tested using LZ4F_isError()) Note : LZ4F_flush() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr).

LZ4F_flush() : When compressed data must be sent immediately, without waiting for a block to be filled, invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx. The result of the function is the number of bytes written into dstBuffer. It can be zero, this means there was no data left within LZ4F_cctx. The function outputs an error code if it fails (can be tested using LZ4F_isError()) LZ4F_compressOptions_t* is optional. NULL is a valid argument.

Definition at line 938 of file lz4frame.c.

941 {
942  BYTE* const dstStart = (BYTE*)dstBuffer;
943  BYTE* dstPtr = dstStart;
945 
946  if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
947  if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
948  if (dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize))
949  return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
950  (void)compressOptionsPtr; /* not yet useful */
951 
952  /* select compression function */
954 
955  /* compress tmp buffer */
956  dstPtr += LZ4F_makeBlock(dstPtr,
957  cctxPtr->tmpIn, cctxPtr->tmpInSize,
958  compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
959  cctxPtr->cdict,
961  assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity));
962 
963  if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)
964  cctxPtr->tmpIn += cctxPtr->tmpInSize;
965  cctxPtr->tmpInSize = 0;
966 
967  /* keep tmpIn within limits */
968  if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */
969  int const realDictSize = LZ4F_localSaveDict(cctxPtr);
970  cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
971  }
972 
973  return (size_t)(dstPtr - dstStart);
974 }

References assert, BFSize, BHSize, LZ4F_frameInfo_t::blockChecksumFlag, LZ4F_frameInfo_t::blockMode, LZ4F_cctx_s::cdict, compress(), LZ4F_preferences_t::compressionLevel, LZ4F_cctx_s::cStage, err0r(), LZ4F_preferences_t::frameInfo, LZ4F_cctx_s::lz4CtxPtr, LZ4F_blockLinked, LZ4F_localSaveDict(), LZ4F_makeBlock(), LZ4F_selectCompression(), LZ4F_cctx_s::maxBlockSize, LZ4F_cctx_s::maxBufferSize, LZ4F_cctx_s::prefs, LZ4F_cctx_s::tmpBuff, LZ4F_cctx_s::tmpIn, and LZ4F_cctx_s::tmpInSize.

Referenced by fuzzerTests(), and LZ4F_compressEnd().

◆ LZ4F_freeCompressionContext()

LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext ( LZ4F_cctx cctx)

Definition at line 550 of file lz4frame.c.

551 {
552  if (cctxPtr != NULL) { /* support free on NULL */
553  FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */
554  FREEMEM(cctxPtr->tmpBuff);
555  FREEMEM(cctxPtr);
556  }
557 
558  return LZ4F_OK_NoError;
559 }

References FREEMEM, LZ4F_cctx_s::lz4CtxPtr, NULL, and LZ4F_cctx_s::tmpBuff.

Referenced by basicTests(), compress_file(), fuzzerTests(), LZ4F_compressFrame(), and LZ4IO_freeCResources().

◆ LZ4F_freeDecompressionContext()

LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext ( LZ4F_dctx dctx)

Definition at line 1082 of file lz4frame.c.

1083 {
1084  LZ4F_errorCode_t result = LZ4F_OK_NoError;
1085  if (dctx != NULL) { /* can accept NULL input, like free() */
1086  result = (LZ4F_errorCode_t)dctx->dStage;
1087  FREEMEM(dctx->tmpIn);
1088  FREEMEM(dctx->tmpOutBuffer);
1089  FREEMEM(dctx);
1090  }
1091  return result;
1092 }
size_t LZ4F_errorCode_t
Definition: lz4frame.h:103

References LZ4F_dctx_s::dStage, FREEMEM, NULL, LZ4F_dctx_s::tmpIn, and LZ4F_dctx_s::tmpOutBuffer.

Referenced by basicTests(), decompress_file(), freeCResources(), fullSpeedBench(), FUZZ_decompressFrame(), fuzzerTests(), LLVMFuzzerTestOneInput(), LZ4IO_freeDResources(), and LZ4IO_getCompressedFileInfo().

◆ LZ4F_getErrorName()

LZ4FLIB_API const char* LZ4F_getErrorName ( LZ4F_errorCode_t  code)

return error code string; for debugging

Definition at line 254 of file lz4frame.c.

255 {
256  static const char* codeError = "Unspecified error code";
257  if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];
258  return codeError;
259 }
static const char * LZ4F_errorStrings[]
Definition: lz4frame.c:246
static int
Definition: sfsocketcall.h:114
Definition: inftree9.h:24

References int, LZ4F_errorStrings, and LZ4F_isError().

Referenced by basicTests(), decompress_file(), decompress_file_allocDst(), decompress_file_internal(), frameCheck(), fuzzerTests(), LZ4IO_compressFilename_extRess(), LZ4IO_createCResources(), LZ4IO_createDResources(), LZ4IO_decompressLZ4F(), LZ4IO_freeCResources(), and LZ4IO_freeDResources().

◆ LZ4F_getFrameInfo()

LZ4FLIB_API size_t LZ4F_getFrameInfo ( LZ4F_dctx dctx,
LZ4F_frameInfo_t frameInfoPtr,
const void *  srcBuffer,
size_t srcSizePtr 
)

LZ4F_getFrameInfo() : This function extracts frame parameters (max blockSize, dictID, etc.). Its usage is optional: user can call LZ4F_decompress() directly.

Extracted information will fill an existing LZ4F_frameInfo_t structure. This can be useful for allocation and dictionary identification purposes.

LZ4F_getFrameInfo() can work in the following situations :

1) At the beginning of a new frame, before any invocation of LZ4F_decompress(). It will decode header from srcBuffer, consuming the header and starting the decoding process.

Input size must be large enough to contain the full frame header. Frame header size can be known beforehand by LZ4F_headerSize(). Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes, and not more than <= LZ4F_HEADER_SIZE_MAX bytes. Hence, blindly providing LZ4F_HEADER_SIZE_MAX bytes or more will always work. It's allowed to provide more input data than the header size, LZ4F_getFrameInfo() will only consume the header.

If input size is not large enough, aka if it's smaller than header size, function will fail and return an error code.

2) After decoding has been started, it's possible to invoke LZ4F_getFrameInfo() anytime to extract already decoded frame parameters stored within dctx.

Note that, if decoding has barely started, and not yet read enough information to decode the header, LZ4F_getFrameInfo() will fail.

The number of bytes consumed from srcBuffer will be updated in *srcSizePtr (necessarily <= original value). LZ4F_getFrameInfo() only consumes bytes when decoding has not yet started, and when decoding the header has been successful. Decompression must then resume from (srcBuffer + *srcSizePtr).

Returns
: a hint about how many srcSize bytes LZ4F_decompress() expects for next call, or an error code which can be tested using LZ4F_isError(). note 1 : in case of error, dctx is not modified. Decoding operation can resume from beginning safely. note 2 : frame parameters are copied into an already allocated LZ4F_frameInfo_t structure.

LZ4F_getFrameInfo() : This function extracts frame parameters (max blockSize, frame checksum, etc.). Usage is optional. Objective is to provide relevant information for allocation purposes. This function works in 2 situations :

  • At the beginning of a new frame, in which case it will decode this information from srcBuffer, and start the decoding process. Amount of input data provided must be large enough to successfully decode the frame header. A header size is variable, but is guaranteed to be <= LZ4F_HEADER_SIZE_MAX bytes. It's possible to provide more input data than this minimum.
  • After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx. The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value). Decompression must resume from (srcBuffer + *srcSizePtr).
    Returns
    : an hint about how many srcSize bytes LZ4F_decompress() expects for next call, or an error code which can be tested using LZ4F_isError() note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped. note 2 : frame parameters are copied into an already allocated LZ4F_frameInfo_t structure.

Definition at line 1253 of file lz4frame.c.

1256 {
1258  if (dctx->dStage > dstage_storeFrameHeader) {
1259  /* frameInfo already decoded */
1260  size_t o=0, i=0;
1261  *srcSizePtr = 0;
1262  *frameInfoPtr = dctx->frameInfo;
1263  /* returns : recommended nb of bytes for LZ4F_decompress() */
1264  return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL);
1265  } else {
1266  if (dctx->dStage == dstage_storeFrameHeader) {
1267  /* frame decoding already started, in the middle of header => automatic fail */
1268  *srcSizePtr = 0;
1269  return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted);
1270  } else {
1271  size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
1272  if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
1273  if (*srcSizePtr < hSize) {
1274  *srcSizePtr=0;
1275  return err0r(LZ4F_ERROR_frameHeader_incomplete);
1276  }
1277 
1278  { size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
1279  if (LZ4F_isError(decodeResult)) {
1280  *srcSizePtr = 0;
1281  } else {
1282  *srcSizePtr = decodeResult;
1283  decodeResult = BHSize; /* block header size */
1284  }
1285  *frameInfoPtr = dctx->frameInfo;
1286  return decodeResult;
1287  } } }
1288 }
lzma_index ** i
Definition: index.h:629
size_t LZ4F_decompress(LZ4F_dctx *dctx, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, const LZ4F_decompressOptions_t *decompressOptionsPtr)
Definition: lz4frame.c:1384
size_t LZ4F_headerSize(const void *src, size_t srcSize)
Definition: lz4frame.c:1212

References BHSize, LZ4F_dctx_s::dStage, dstage_getFrameHeader, dstage_storeFrameHeader, err0r(), LZ4F_dctx_s::frameInfo, i, LZ4F_decodeHeader(), LZ4F_decompress(), LZ4F_headerSize(), LZ4F_isError(), LZ4F_STATIC_ASSERT, and NULL.

Referenced by basicTests(), decompress_file_allocDst(), frameCheck(), and LZ4IO_getCompressedFileInfo().

◆ LZ4F_getVersion()

LZ4FLIB_API unsigned LZ4F_getVersion ( void  )

Definition at line 274 of file lz4frame.c.

274 { return LZ4F_VERSION; }

References LZ4F_VERSION.

◆ LZ4F_headerSize()

LZ4FLIB_API size_t LZ4F_headerSize ( const void *  src,
size_t  srcSize 
)

LZ4F_headerSize() : v1.9.0+ Provide the header size of a frame starting at src. srcSize must be >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH, which is enough to decode the header length.

Returns
: size of frame header or an error code, which can be tested using LZ4F_isError() note : Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes.

LZ4F_headerSize() :

Returns
: size of frame header or an error code, which can be tested using LZ4F_isError()

Definition at line 1212 of file lz4frame.c.

1213 {
1214  if (src == NULL) return err0r(LZ4F_ERROR_srcPtr_wrong);
1215 
1216  /* minimal srcSize to determine header size */
1218  return err0r(LZ4F_ERROR_frameHeader_incomplete);
1219 
1220  /* special case : skippable frames */
1221  if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
1222  return 8;
1223 
1224  /* control magic number */
1225 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1227  return err0r(LZ4F_ERROR_frameType_unknown);
1228 #endif
1229 
1230  /* Frame Header Size */
1231  { BYTE const FLG = ((const BYTE*)src)[4];
1232  U32 const contentSizeFlag = (FLG>>3) & _1BIT;
1233  U32 const dictIDFlag = FLG & _1BIT;
1234  return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
1235  }
1236 }
lzma_index * src
Definition: index.h:567
#define FLG(x)
Definition: esil.c:10
#define LZ4F_MAGIC_SKIPPABLE_START
Definition: lz4frame.c:209
#define LZ4F_MAGICNUMBER
Definition: lz4frame.c:210
#define _1BIT
Definition: lz4frame.c:203
#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH
Definition: lz4frame.h:374

References _1BIT, err0r(), FLG, LZ4F_MAGIC_SKIPPABLE_START, LZ4F_MAGICNUMBER, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH, LZ4F_readLE32(), minFHSize, NULL, src, and srcSize.

Referenced by basicTests(), LZ4F_getFrameInfo(), and LZ4IO_getCompressedFileInfo().

◆ LZ4F_isError()

◆ LZ4F_resetDecompressionContext()

LZ4FLIB_API void LZ4F_resetDecompressionContext ( LZ4F_dctx dctx)

LZ4F_resetDecompressionContext() : added in v1.8.0 In case of an error, the context is left in "undefined" state. In which case, it's necessary to reset it, before re-using it. This method can also be used to abruptly stop any unfinished decompression, and start a new one using same context resources.

Definition at line 1097 of file lz4frame.c.

1098 {
1099  dctx->dStage = dstage_getFrameHeader;
1100  dctx->dict = NULL;
1101  dctx->dictSize = 0;
1102 }

References LZ4F_dctx_s::dict, LZ4F_dctx_s::dictSize, LZ4F_dctx_s::dStage, dstage_getFrameHeader, and NULL.

Referenced by basicTests(), decompress(), fuzzerTests(), and LZ4F_decompress().