lz4frame.c 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899
  1. /*
  2. * LZ4 auto-framing library
  3. * Copyright (C) 2011-2016, Yann Collet.
  4. *
  5. * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * - Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * - Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following disclaimer
  15. * in the documentation and/or other materials provided with the
  16. * distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * You can contact the author at :
  31. * - LZ4 homepage : http://www.lz4.org
  32. * - LZ4 source repository : https://github.com/lz4/lz4
  33. */
  34. /* LZ4F is a stand-alone API to create LZ4-compressed Frames
  35. * in full conformance with specification v1.6.1 .
  36. * This library rely upon memory management capabilities (malloc, free)
  37. * provided either by <stdlib.h>,
  38. * or redirected towards another library of user's choice
  39. * (see Memory Routines below).
  40. */
  41. /*-************************************
  42. * Compiler Options
  43. **************************************/
  44. #ifdef _MSC_VER /* Visual Studio */
  45. # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
  46. #endif
  47. /*-************************************
  48. * Tuning parameters
  49. **************************************/
  50. /*
  51. * LZ4F_HEAPMODE :
  52. * Select how default compression functions will allocate memory for their hash table,
  53. * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
  54. */
  55. #ifndef LZ4F_HEAPMODE
  56. # define LZ4F_HEAPMODE 0
  57. #endif
  58. /*-************************************
  59. * Memory routines
  60. **************************************/
  61. /*
  62. * User may redirect invocations of
  63. * malloc(), calloc() and free()
  64. * towards another library or solution of their choice
  65. * by modifying below section.
  66. */
  67. #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
  68. # include <stdlib.h> /* malloc, calloc, free */
  69. # define ALLOC(s) malloc(s)
  70. # define ALLOC_AND_ZERO(s) calloc(1,(s))
  71. # define FREEMEM(p) free(p)
  72. #endif
  73. #include <string.h> /* memset, memcpy, memmove */
  74. #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
  75. # define MEM_INIT(p,v,s) memset((p),(v),(s))
  76. #endif
  77. /*-************************************
  78. * Library declarations
  79. **************************************/
  80. #define LZ4F_STATIC_LINKING_ONLY
  81. #include "lz4frame.h"
  82. #define LZ4_STATIC_LINKING_ONLY
  83. #include "lz4.h"
  84. #define LZ4_HC_STATIC_LINKING_ONLY
  85. #include "lz4hc.h"
  86. #define XXH_STATIC_LINKING_ONLY
  87. #include "xxhash.h"
  88. /*-************************************
  89. * Debug
  90. **************************************/
  91. #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)
  92. # include <assert.h>
  93. #else
  94. # ifndef assert
  95. # define assert(condition) ((void)0)
  96. # endif
  97. #endif
  98. #define LZ4F_STATIC_ASSERT(c) { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
  99. #if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) && !defined(DEBUGLOG)
  100. # include <stdio.h>
  101. static int g_debuglog_enable = 1;
  102. # define DEBUGLOG(l, ...) { \
  103. if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \
  104. fprintf(stderr, __FILE__ ": "); \
  105. fprintf(stderr, __VA_ARGS__); \
  106. fprintf(stderr, " \n"); \
  107. } }
  108. #else
  109. # define DEBUGLOG(l, ...) {} /* disabled */
  110. #endif
  111. /*-************************************
  112. * Basic Types
  113. **************************************/
  114. #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
  115. # include <stdint.h>
  116. typedef uint8_t BYTE;
  117. typedef uint16_t U16;
  118. typedef uint32_t U32;
  119. typedef int32_t S32;
  120. typedef uint64_t U64;
  121. #else
  122. typedef unsigned char BYTE;
  123. typedef unsigned short U16;
  124. typedef unsigned int U32;
  125. typedef signed int S32;
  126. typedef unsigned long long U64;
  127. #endif
  128. /* unoptimized version; solves endianess & alignment issues */
  129. static U32 LZ4F_readLE32 (const void* src)
  130. {
  131. const BYTE* const srcPtr = (const BYTE*)src;
  132. U32 value32 = srcPtr[0];
  133. value32 += ((U32)srcPtr[1])<< 8;
  134. value32 += ((U32)srcPtr[2])<<16;
  135. value32 += ((U32)srcPtr[3])<<24;
  136. return value32;
  137. }
  138. static void LZ4F_writeLE32 (void* dst, U32 value32)
  139. {
  140. BYTE* const dstPtr = (BYTE*)dst;
  141. dstPtr[0] = (BYTE)value32;
  142. dstPtr[1] = (BYTE)(value32 >> 8);
  143. dstPtr[2] = (BYTE)(value32 >> 16);
  144. dstPtr[3] = (BYTE)(value32 >> 24);
  145. }
  146. static U64 LZ4F_readLE64 (const void* src)
  147. {
  148. const BYTE* const srcPtr = (const BYTE*)src;
  149. U64 value64 = srcPtr[0];
  150. value64 += ((U64)srcPtr[1]<<8);
  151. value64 += ((U64)srcPtr[2]<<16);
  152. value64 += ((U64)srcPtr[3]<<24);
  153. value64 += ((U64)srcPtr[4]<<32);
  154. value64 += ((U64)srcPtr[5]<<40);
  155. value64 += ((U64)srcPtr[6]<<48);
  156. value64 += ((U64)srcPtr[7]<<56);
  157. return value64;
  158. }
  159. static void LZ4F_writeLE64 (void* dst, U64 value64)
  160. {
  161. BYTE* const dstPtr = (BYTE*)dst;
  162. dstPtr[0] = (BYTE)value64;
  163. dstPtr[1] = (BYTE)(value64 >> 8);
  164. dstPtr[2] = (BYTE)(value64 >> 16);
  165. dstPtr[3] = (BYTE)(value64 >> 24);
  166. dstPtr[4] = (BYTE)(value64 >> 32);
  167. dstPtr[5] = (BYTE)(value64 >> 40);
  168. dstPtr[6] = (BYTE)(value64 >> 48);
  169. dstPtr[7] = (BYTE)(value64 >> 56);
  170. }
  171. /*-************************************
  172. * Constants
  173. **************************************/
  174. #ifndef LZ4_SRC_INCLUDED /* avoid double definition */
  175. # define KB *(1<<10)
  176. # define MB *(1<<20)
  177. # define GB *(1<<30)
  178. #endif
  179. #define _1BIT 0x01
  180. #define _2BITS 0x03
  181. #define _3BITS 0x07
  182. #define _4BITS 0x0F
  183. #define _8BITS 0xFF
  184. #define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
  185. #define LZ4F_MAGICNUMBER 0x184D2204U
  186. #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
  187. #define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB
  188. static const size_t minFHSize = LZ4F_HEADER_SIZE_MIN; /* 7 */
  189. static const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX; /* 19 */
  190. static const size_t BHSize = LZ4F_BLOCK_HEADER_SIZE; /* block header : size, and compress flag */
  191. static const size_t BFSize = LZ4F_BLOCK_CHECKSUM_SIZE; /* block footer : checksum (optional) */
  192. /*-************************************
  193. * Structures and local types
  194. **************************************/
  195. typedef struct LZ4F_cctx_s
  196. {
  197. LZ4F_preferences_t prefs;
  198. U32 version;
  199. U32 cStage;
  200. const LZ4F_CDict* cdict;
  201. size_t maxBlockSize;
  202. size_t maxBufferSize;
  203. BYTE* tmpBuff;
  204. BYTE* tmpIn;
  205. size_t tmpInSize;
  206. U64 totalInSize;
  207. XXH32_state_t xxh;
  208. void* lz4CtxPtr;
  209. U16 lz4CtxAlloc; /* sized for: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */
  210. U16 lz4CtxState; /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */
  211. } LZ4F_cctx_t;
  212. /*-************************************
  213. * Error management
  214. **************************************/
  215. #define LZ4F_GENERATE_STRING(STRING) #STRING,
  216. static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };
  217. unsigned LZ4F_isError(LZ4F_errorCode_t code)
  218. {
  219. return (code > (LZ4F_errorCode_t)(-LZ4F_ERROR_maxCode));
  220. }
  221. const char* LZ4F_getErrorName(LZ4F_errorCode_t code)
  222. {
  223. static const char* codeError = "Unspecified error code";
  224. if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];
  225. return codeError;
  226. }
  227. LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult)
  228. {
  229. if (!LZ4F_isError(functionResult)) return LZ4F_OK_NoError;
  230. return (LZ4F_errorCodes)(-(ptrdiff_t)functionResult);
  231. }
  232. static LZ4F_errorCode_t err0r(LZ4F_errorCodes code)
  233. {
  234. /* A compilation error here means sizeof(ptrdiff_t) is not large enough */
  235. LZ4F_STATIC_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t));
  236. return (LZ4F_errorCode_t)-(ptrdiff_t)code;
  237. }
  238. unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; }
  239. int LZ4F_compressionLevel_max(void) { return LZ4HC_CLEVEL_MAX; }
  240. size_t LZ4F_getBlockSize(unsigned blockSizeID)
  241. {
  242. static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };
  243. if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
  244. if (blockSizeID < LZ4F_max64KB || blockSizeID > LZ4F_max4MB)
  245. return err0r(LZ4F_ERROR_maxBlockSize_invalid);
  246. blockSizeID -= LZ4F_max64KB;
  247. return blockSizes[blockSizeID];
  248. }
  249. /*-************************************
  250. * Private functions
  251. **************************************/
  252. #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
  253. static BYTE LZ4F_headerChecksum (const void* header, size_t length)
  254. {
  255. U32 const xxh = XXH32(header, length, 0);
  256. return (BYTE)(xxh >> 8);
  257. }
  258. /*-************************************
  259. * Simple-pass compression functions
  260. **************************************/
  261. static LZ4F_blockSizeID_t LZ4F_optimalBSID(const LZ4F_blockSizeID_t requestedBSID,
  262. const size_t srcSize)
  263. {
  264. LZ4F_blockSizeID_t proposedBSID = LZ4F_max64KB;
  265. size_t maxBlockSize = 64 KB;
  266. while (requestedBSID > proposedBSID) {
  267. if (srcSize <= maxBlockSize)
  268. return proposedBSID;
  269. proposedBSID = (LZ4F_blockSizeID_t)((int)proposedBSID + 1);
  270. maxBlockSize <<= 2;
  271. }
  272. return requestedBSID;
  273. }
  274. /*! LZ4F_compressBound_internal() :
  275. * Provides dstCapacity given a srcSize to guarantee operation success in worst case situations.
  276. * prefsPtr is optional : if NULL is provided, preferences will be set to cover worst case scenario.
  277. * @return is always the same for a srcSize and prefsPtr, so it can be relied upon to size reusable buffers.
  278. * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations.
  279. */
  280. static size_t LZ4F_compressBound_internal(size_t srcSize,
  281. const LZ4F_preferences_t* preferencesPtr,
  282. size_t alreadyBuffered)
  283. {
  284. LZ4F_preferences_t prefsNull = LZ4F_INIT_PREFERENCES;
  285. prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */
  286. prefsNull.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled; /* worst case */
  287. { const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;
  288. U32 const flush = prefsPtr->autoFlush | (srcSize==0);
  289. LZ4F_blockSizeID_t const blockID = prefsPtr->frameInfo.blockSizeID;
  290. size_t const blockSize = LZ4F_getBlockSize(blockID);
  291. size_t const maxBuffered = blockSize - 1;
  292. size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered);
  293. size_t const maxSrcSize = srcSize + bufferedSize;
  294. unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize);
  295. size_t const partialBlockSize = maxSrcSize & (blockSize-1);
  296. size_t const lastBlockSize = flush ? partialBlockSize : 0;
  297. unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0);
  298. size_t const blockCRCSize = BFSize * prefsPtr->frameInfo.blockChecksumFlag;
  299. size_t const frameEnd = BHSize + (prefsPtr->frameInfo.contentChecksumFlag*BFSize);
  300. return ((BHSize + blockCRCSize) * nbBlocks) +
  301. (blockSize * nbFullBlocks) + lastBlockSize + frameEnd;
  302. }
  303. }
  304. size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
  305. {
  306. LZ4F_preferences_t prefs;
  307. size_t const headerSize = maxFHSize; /* max header size, including optional fields */
  308. if (preferencesPtr!=NULL) prefs = *preferencesPtr;
  309. else MEM_INIT(&prefs, 0, sizeof(prefs));
  310. prefs.autoFlush = 1;
  311. return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);;
  312. }
  313. /*! LZ4F_compressFrame_usingCDict() :
  314. * Compress srcBuffer using a dictionary, in a single step.
  315. * cdict can be NULL, in which case, no dictionary is used.
  316. * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
  317. * The LZ4F_preferences_t structure is optional : you may provide NULL as argument,
  318. * however, it's the only way to provide a dictID, so it's not recommended.
  319. * @return : number of bytes written into dstBuffer,
  320. * or an error code if it fails (can be tested using LZ4F_isError())
  321. */
  322. size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx,
  323. void* dstBuffer, size_t dstCapacity,
  324. const void* srcBuffer, size_t srcSize,
  325. const LZ4F_CDict* cdict,
  326. const LZ4F_preferences_t* preferencesPtr)
  327. {
  328. LZ4F_preferences_t prefs;
  329. LZ4F_compressOptions_t options;
  330. BYTE* const dstStart = (BYTE*) dstBuffer;
  331. BYTE* dstPtr = dstStart;
  332. BYTE* const dstEnd = dstStart + dstCapacity;
  333. if (preferencesPtr!=NULL)
  334. prefs = *preferencesPtr;
  335. else
  336. MEM_INIT(&prefs, 0, sizeof(prefs));
  337. if (prefs.frameInfo.contentSize != 0)
  338. prefs.frameInfo.contentSize = (U64)srcSize; /* auto-correct content size if selected (!=0) */
  339. prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
  340. prefs.autoFlush = 1;
  341. if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))
  342. prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* only one block => no need for inter-block link */
  343. MEM_INIT(&options, 0, sizeof(options));
  344. options.stableSrc = 1;
  345. if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs)) /* condition to guarantee success */
  346. return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  347. { size_t const headerSize = LZ4F_compressBegin_usingCDict(cctx, dstBuffer, dstCapacity, cdict, &prefs); /* write header */
  348. if (LZ4F_isError(headerSize)) return headerSize;
  349. dstPtr += headerSize; /* header size */ }
  350. assert(dstEnd >= dstPtr);
  351. { size_t const cSize = LZ4F_compressUpdate(cctx, dstPtr, (size_t)(dstEnd-dstPtr), srcBuffer, srcSize, &options);
  352. if (LZ4F_isError(cSize)) return cSize;
  353. dstPtr += cSize; }
  354. assert(dstEnd >= dstPtr);
  355. { size_t const tailSize = LZ4F_compressEnd(cctx, dstPtr, (size_t)(dstEnd-dstPtr), &options); /* flush last block, and generate suffix */
  356. if (LZ4F_isError(tailSize)) return tailSize;
  357. dstPtr += tailSize; }
  358. assert(dstEnd >= dstStart);
  359. return (size_t)(dstPtr - dstStart);
  360. }
  361. /*! LZ4F_compressFrame() :
  362. * Compress an entire srcBuffer into a valid LZ4 frame, in a single step.
  363. * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
  364. * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
  365. * @return : number of bytes written into dstBuffer.
  366. * or an error code if it fails (can be tested using LZ4F_isError())
  367. */
  368. size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,
  369. const void* srcBuffer, size_t srcSize,
  370. const LZ4F_preferences_t* preferencesPtr)
  371. {
  372. size_t result;
  373. #if (LZ4F_HEAPMODE)
  374. LZ4F_cctx_t *cctxPtr;
  375. result = LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION);
  376. if (LZ4F_isError(result)) return result;
  377. #else
  378. LZ4F_cctx_t cctx;
  379. LZ4_stream_t lz4ctx;
  380. LZ4F_cctx_t *cctxPtr = &cctx;
  381. DEBUGLOG(4, "LZ4F_compressFrame");
  382. MEM_INIT(&cctx, 0, sizeof(cctx));
  383. cctx.version = LZ4F_VERSION;
  384. cctx.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */
  385. if (preferencesPtr == NULL ||
  386. preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN)
  387. {
  388. LZ4_initStream(&lz4ctx, sizeof(lz4ctx));
  389. cctxPtr->lz4CtxPtr = &lz4ctx;
  390. cctxPtr->lz4CtxAlloc = 1;
  391. cctxPtr->lz4CtxState = 1;
  392. }
  393. #endif
  394. result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity,
  395. srcBuffer, srcSize,
  396. NULL, preferencesPtr);
  397. #if (LZ4F_HEAPMODE)
  398. LZ4F_freeCompressionContext(cctxPtr);
  399. #else
  400. if (preferencesPtr != NULL &&
  401. preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN)
  402. {
  403. FREEMEM(cctxPtr->lz4CtxPtr);
  404. }
  405. #endif
  406. return result;
  407. }
  408. /*-***************************************************
  409. * Dictionary compression
  410. *****************************************************/
  411. struct LZ4F_CDict_s {
  412. void* dictContent;
  413. LZ4_stream_t* fastCtx;
  414. LZ4_streamHC_t* HCCtx;
  415. }; /* typedef'd to LZ4F_CDict within lz4frame_static.h */
  416. /*! LZ4F_createCDict() :
  417. * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
  418. * LZ4F_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
  419. * LZ4F_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
  420. * `dictBuffer` can be released after LZ4F_CDict creation, since its content is copied within CDict
  421. * @return : digested dictionary for compression, or NULL if failed */
  422. LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize)
  423. {
  424. const char* dictStart = (const char*)dictBuffer;
  425. LZ4F_CDict* cdict = (LZ4F_CDict*) ALLOC(sizeof(*cdict));
  426. DEBUGLOG(4, "LZ4F_createCDict");
  427. if (!cdict) return NULL;
  428. if (dictSize > 64 KB) {
  429. dictStart += dictSize - 64 KB;
  430. dictSize = 64 KB;
  431. }
  432. cdict->dictContent = ALLOC(dictSize);
  433. cdict->fastCtx = LZ4_createStream();
  434. cdict->HCCtx = LZ4_createStreamHC();
  435. if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) {
  436. LZ4F_freeCDict(cdict);
  437. return NULL;
  438. }
  439. memcpy(cdict->dictContent, dictStart, dictSize);
  440. LZ4_loadDict (cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize);
  441. LZ4_setCompressionLevel(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT);
  442. LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize);
  443. return cdict;
  444. }
  445. void LZ4F_freeCDict(LZ4F_CDict* cdict)
  446. {
  447. if (cdict==NULL) return; /* support free on NULL */
  448. FREEMEM(cdict->dictContent);
  449. LZ4_freeStream(cdict->fastCtx);
  450. LZ4_freeStreamHC(cdict->HCCtx);
  451. FREEMEM(cdict);
  452. }
  453. /*-*********************************
  454. * Advanced compression functions
  455. ***********************************/
  456. /*! LZ4F_createCompressionContext() :
  457. * The first thing to do is to create a compressionContext object, which will be used in all compression operations.
  458. * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
  459. * The version provided MUST be LZ4F_VERSION. It is intended to track potential incompatible differences between different binaries.
  460. * The function will provide a pointer to an allocated LZ4F_compressionContext_t object.
  461. * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
  462. * Object can release its memory using LZ4F_freeCompressionContext();
  463. */
  464. LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version)
  465. {
  466. LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t));
  467. if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
  468. cctxPtr->version = version;
  469. cctxPtr->cStage = 0; /* Next stage : init stream */
  470. *LZ4F_compressionContextPtr = cctxPtr;
  471. return LZ4F_OK_NoError;
  472. }
  473. LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr)
  474. {
  475. if (cctxPtr != NULL) { /* support free on NULL */
  476. FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */
  477. FREEMEM(cctxPtr->tmpBuff);
  478. FREEMEM(cctxPtr);
  479. }
  480. return LZ4F_OK_NoError;
  481. }
  482. /**
  483. * This function prepares the internal LZ4(HC) stream for a new compression,
  484. * resetting the context and attaching the dictionary, if there is one.
  485. *
  486. * It needs to be called at the beginning of each independent compression
  487. * stream (i.e., at the beginning of a frame in blockLinked mode, or at the
  488. * beginning of each block in blockIndependent mode).
  489. */
  490. static void LZ4F_initStream(void* ctx,
  491. const LZ4F_CDict* cdict,
  492. int level,
  493. LZ4F_blockMode_t blockMode) {
  494. if (level < LZ4HC_CLEVEL_MIN) {
  495. if (cdict != NULL || blockMode == LZ4F_blockLinked) {
  496. /* In these cases, we will call LZ4_compress_fast_continue(),
  497. * which needs an already reset context. Otherwise, we'll call a
  498. * one-shot API. The non-continued APIs internally perform their own
  499. * resets at the beginning of their calls, where they know what
  500. * tableType they need the context to be in. So in that case this
  501. * would be misguided / wasted work. */
  502. LZ4_resetStream_fast((LZ4_stream_t*)ctx);
  503. }
  504. LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL);
  505. } else {
  506. LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level);
  507. LZ4_attach_HC_dictionary((LZ4_streamHC_t *)ctx, cdict ? cdict->HCCtx : NULL);
  508. }
  509. }
  510. /*! LZ4F_compressBegin_usingCDict() :
  511. * init streaming compression and writes frame header into dstBuffer.
  512. * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
  513. * @return : number of bytes written into dstBuffer for the header
  514. * or an error code (can be tested using LZ4F_isError())
  515. */
  516. size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
  517. void* dstBuffer, size_t dstCapacity,
  518. const LZ4F_CDict* cdict,
  519. const LZ4F_preferences_t* preferencesPtr)
  520. {
  521. LZ4F_preferences_t prefNull;
  522. BYTE* const dstStart = (BYTE*)dstBuffer;
  523. BYTE* dstPtr = dstStart;
  524. BYTE* headerStart;
  525. if (dstCapacity < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  526. MEM_INIT(&prefNull, 0, sizeof(prefNull));
  527. if (preferencesPtr == NULL) preferencesPtr = &prefNull;
  528. cctxPtr->prefs = *preferencesPtr;
  529. /* Ctx Management */
  530. { U16 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2;
  531. if (cctxPtr->lz4CtxAlloc < ctxTypeID) {
  532. FREEMEM(cctxPtr->lz4CtxPtr);
  533. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
  534. cctxPtr->lz4CtxPtr = LZ4_createStream();
  535. } else {
  536. cctxPtr->lz4CtxPtr = LZ4_createStreamHC();
  537. }
  538. if (cctxPtr->lz4CtxPtr == NULL)
  539. return err0r(LZ4F_ERROR_allocation_failed);
  540. cctxPtr->lz4CtxAlloc = ctxTypeID;
  541. cctxPtr->lz4CtxState = ctxTypeID;
  542. } else if (cctxPtr->lz4CtxState != ctxTypeID) {
  543. /* otherwise, a sufficient buffer is allocated, but we need to
  544. * reset it to the correct context type */
  545. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
  546. LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t));
  547. } else {
  548. LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t));
  549. LZ4_setCompressionLevel((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
  550. }
  551. cctxPtr->lz4CtxState = ctxTypeID;
  552. }
  553. }
  554. /* Buffer Management */
  555. if (cctxPtr->prefs.frameInfo.blockSizeID == 0)
  556. cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
  557. cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
  558. { size_t const requiredBuffSize = preferencesPtr->autoFlush ?
  559. ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */
  560. cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0);
  561. if (cctxPtr->maxBufferSize < requiredBuffSize) {
  562. cctxPtr->maxBufferSize = 0;
  563. FREEMEM(cctxPtr->tmpBuff);
  564. cctxPtr->tmpBuff = (BYTE*)ALLOC_AND_ZERO(requiredBuffSize);
  565. if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed);
  566. cctxPtr->maxBufferSize = requiredBuffSize;
  567. } }
  568. cctxPtr->tmpIn = cctxPtr->tmpBuff;
  569. cctxPtr->tmpInSize = 0;
  570. (void)XXH32_reset(&(cctxPtr->xxh), 0);
  571. /* context init */
  572. cctxPtr->cdict = cdict;
  573. if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) {
  574. /* frame init only for blockLinked : blockIndependent will be init at each block */
  575. LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked);
  576. }
  577. if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) {
  578. LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed);
  579. }
  580. /* Magic Number */
  581. LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);
  582. dstPtr += 4;
  583. headerStart = dstPtr;
  584. /* FLG Byte */
  585. *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */
  586. + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)
  587. + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4)
  588. + ((unsigned)(cctxPtr->prefs.frameInfo.contentSize > 0) << 3)
  589. + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)
  590. + (cctxPtr->prefs.frameInfo.dictID > 0) );
  591. /* BD Byte */
  592. *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
  593. /* Optional Frame content size field */
  594. if (cctxPtr->prefs.frameInfo.contentSize) {
  595. LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);
  596. dstPtr += 8;
  597. cctxPtr->totalInSize = 0;
  598. }
  599. /* Optional dictionary ID field */
  600. if (cctxPtr->prefs.frameInfo.dictID) {
  601. LZ4F_writeLE32(dstPtr, cctxPtr->prefs.frameInfo.dictID);
  602. dstPtr += 4;
  603. }
  604. /* Header CRC Byte */
  605. *dstPtr = LZ4F_headerChecksum(headerStart, (size_t)(dstPtr - headerStart));
  606. dstPtr++;
  607. cctxPtr->cStage = 1; /* header written, now request input data block */
  608. return (size_t)(dstPtr - dstStart);
  609. }
  610. /*! LZ4F_compressBegin() :
  611. * init streaming compression and writes frame header into dstBuffer.
  612. * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
  613. * preferencesPtr can be NULL, in which case default parameters are selected.
  614. * @return : number of bytes written into dstBuffer for the header
  615. * or an error code (can be tested using LZ4F_isError())
  616. */
  617. size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
  618. void* dstBuffer, size_t dstCapacity,
  619. const LZ4F_preferences_t* preferencesPtr)
  620. {
  621. return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity,
  622. NULL, preferencesPtr);
  623. }
  624. /* LZ4F_compressBound() :
  625. * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario.
  626. * LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario.
  627. * This function cannot fail.
  628. */
  629. size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
  630. {
  631. if (preferencesPtr && preferencesPtr->autoFlush) {
  632. return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0);
  633. }
  634. return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);
  635. }
  636. typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level, const LZ4F_CDict* cdict);
  637. /*! LZ4F_makeBlock():
  638. * compress a single block, add header and optional checksum.
  639. * assumption : dst buffer capacity is >= BHSize + srcSize + crcSize
  640. */
  641. static size_t LZ4F_makeBlock(void* dst,
  642. const void* src, size_t srcSize,
  643. compressFunc_t compress, void* lz4ctx, int level,
  644. const LZ4F_CDict* cdict,
  645. LZ4F_blockChecksum_t crcFlag)
  646. {
  647. BYTE* const cSizePtr = (BYTE*)dst;
  648. U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+BHSize),
  649. (int)(srcSize), (int)(srcSize-1),
  650. level, cdict);
  651. if (cSize == 0) { /* compression failed */
  652. DEBUGLOG(5, "LZ4F_makeBlock: compression failed, creating a raw block (size %u)", (U32)srcSize);
  653. cSize = (U32)srcSize;
  654. LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);
  655. memcpy(cSizePtr+BHSize, src, srcSize);
  656. } else {
  657. LZ4F_writeLE32(cSizePtr, cSize);
  658. }
  659. if (crcFlag) {
  660. U32 const crc32 = XXH32(cSizePtr+BHSize, cSize, 0); /* checksum of compressed data */
  661. LZ4F_writeLE32(cSizePtr+BHSize+cSize, crc32);
  662. }
  663. return BHSize + cSize + ((U32)crcFlag)*BFSize;
  664. }
  665. static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  666. {
  667. int const acceleration = (level < 0) ? -level + 1 : 1;
  668. LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
  669. if (cdict) {
  670. return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
  671. } else {
  672. return LZ4_compress_fast_extState_fastReset(ctx, src, dst, srcSize, dstCapacity, acceleration);
  673. }
  674. }
  675. static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  676. {
  677. int const acceleration = (level < 0) ? -level + 1 : 1;
  678. (void)cdict; /* init once at beginning of frame */
  679. return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
  680. }
  681. static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  682. {
  683. LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
  684. if (cdict) {
  685. return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
  686. }
  687. return LZ4_compress_HC_extStateHC_fastReset(ctx, src, dst, srcSize, dstCapacity, level);
  688. }
  689. static int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  690. {
  691. (void)level; (void)cdict; /* init once at beginning of frame */
  692. return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
  693. }
  694. static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level)
  695. {
  696. if (level < LZ4HC_CLEVEL_MIN) {
  697. if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock;
  698. return LZ4F_compressBlock_continue;
  699. }
  700. if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlockHC;
  701. return LZ4F_compressBlockHC_continue;
  702. }
  703. static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)
  704. {
  705. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
  706. return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
  707. return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
  708. }
  709. typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
  710. /*! LZ4F_compressUpdate() :
  711. * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
  712. * dstBuffer MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).
  713. * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
  714. * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.
  715. * or an error code if it fails (which can be tested using LZ4F_isError())
  716. */
  717. size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
  718. void* dstBuffer, size_t dstCapacity,
  719. const void* srcBuffer, size_t srcSize,
  720. const LZ4F_compressOptions_t* compressOptionsPtr)
  721. {
  722. LZ4F_compressOptions_t cOptionsNull;
  723. size_t const blockSize = cctxPtr->maxBlockSize;
  724. const BYTE* srcPtr = (const BYTE*)srcBuffer;
  725. const BYTE* const srcEnd = srcPtr + srcSize;
  726. BYTE* const dstStart = (BYTE*)dstBuffer;
  727. BYTE* dstPtr = dstStart;
  728. LZ4F_lastBlockStatus lastBlockCompressed = notDone;
  729. compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
  730. DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize);
  731. if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
  732. if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
  733. return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  734. MEM_INIT(&cOptionsNull, 0, sizeof(cOptionsNull));
  735. if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
  736. /* complete tmp buffer */
  737. if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
  738. size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
  739. if (sizeToCopy > srcSize) {
  740. /* add src to tmpIn buffer */
  741. memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
  742. srcPtr = srcEnd;
  743. cctxPtr->tmpInSize += srcSize;
  744. /* still needs some CRC */
  745. } else {
  746. /* complete tmpIn block and then compress it */
  747. lastBlockCompressed = fromTmpBuffer;
  748. memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
  749. srcPtr += sizeToCopy;
  750. dstPtr += LZ4F_makeBlock(dstPtr,
  751. cctxPtr->tmpIn, blockSize,
  752. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  753. cctxPtr->cdict,
  754. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  755. if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
  756. cctxPtr->tmpInSize = 0;
  757. }
  758. }
  759. while ((size_t)(srcEnd - srcPtr) >= blockSize) {
  760. /* compress full blocks */
  761. lastBlockCompressed = fromSrcBuffer;
  762. dstPtr += LZ4F_makeBlock(dstPtr,
  763. srcPtr, blockSize,
  764. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  765. cctxPtr->cdict,
  766. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  767. srcPtr += blockSize;
  768. }
  769. if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
  770. /* compress remaining input < blockSize */
  771. lastBlockCompressed = fromSrcBuffer;
  772. dstPtr += LZ4F_makeBlock(dstPtr,
  773. srcPtr, (size_t)(srcEnd - srcPtr),
  774. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  775. cctxPtr->cdict,
  776. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  777. srcPtr = srcEnd;
  778. }
  779. /* preserve dictionary if necessary */
  780. if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {
  781. if (compressOptionsPtr->stableSrc) {
  782. cctxPtr->tmpIn = cctxPtr->tmpBuff;
  783. } else {
  784. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  785. if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC);
  786. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  787. }
  788. }
  789. /* keep tmpIn within limits */
  790. if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */
  791. && !(cctxPtr->prefs.autoFlush))
  792. {
  793. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  794. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  795. }
  796. /* some input data left, necessarily < blockSize */
  797. if (srcPtr < srcEnd) {
  798. /* fill tmp buffer */
  799. size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
  800. memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
  801. cctxPtr->tmpInSize = sizeToCopy;
  802. }
  803. if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
  804. (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
  805. cctxPtr->totalInSize += srcSize;
  806. return (size_t)(dstPtr - dstStart);
  807. }
  808. /*! LZ4F_flush() :
  809. * When compressed data must be sent immediately, without waiting for a block to be filled,
  810. * invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx.
  811. * The result of the function is the number of bytes written into dstBuffer.
  812. * It can be zero, this means there was no data left within LZ4F_cctx.
  813. * The function outputs an error code if it fails (can be tested using LZ4F_isError())
  814. * LZ4F_compressOptions_t* is optional. NULL is a valid argument.
  815. */
  816. size_t LZ4F_flush(LZ4F_cctx* cctxPtr,
  817. void* dstBuffer, size_t dstCapacity,
  818. const LZ4F_compressOptions_t* compressOptionsPtr)
  819. {
  820. BYTE* const dstStart = (BYTE*)dstBuffer;
  821. BYTE* dstPtr = dstStart;
  822. compressFunc_t compress;
  823. if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
  824. if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
  825. if (dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize))
  826. return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  827. (void)compressOptionsPtr; /* not yet useful */
  828. /* select compression function */
  829. compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
  830. /* compress tmp buffer */
  831. dstPtr += LZ4F_makeBlock(dstPtr,
  832. cctxPtr->tmpIn, cctxPtr->tmpInSize,
  833. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  834. cctxPtr->cdict,
  835. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  836. assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity));
  837. if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)
  838. cctxPtr->tmpIn += cctxPtr->tmpInSize;
  839. cctxPtr->tmpInSize = 0;
  840. /* keep tmpIn within limits */
  841. if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */
  842. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  843. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  844. }
  845. return (size_t)(dstPtr - dstStart);
  846. }
  847. /*! LZ4F_compressEnd() :
  848. * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
  849. * It will flush whatever data remained within compressionContext (like LZ4_flush())
  850. * but also properly finalize the frame, with an endMark and an (optional) checksum.
  851. * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
  852. * @return: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
  853. * or an error code if it fails (can be tested using LZ4F_isError())
  854. * The context can then be used again to compress a new frame, starting with LZ4F_compressBegin().
  855. */
  856. size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,
  857. void* dstBuffer, size_t dstCapacity,
  858. const LZ4F_compressOptions_t* compressOptionsPtr)
  859. {
  860. BYTE* const dstStart = (BYTE*)dstBuffer;
  861. BYTE* dstPtr = dstStart;
  862. size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
  863. DEBUGLOG(5,"LZ4F_compressEnd: dstCapacity=%u", (unsigned)dstCapacity);
  864. if (LZ4F_isError(flushSize)) return flushSize;
  865. dstPtr += flushSize;
  866. assert(flushSize <= dstCapacity);
  867. dstCapacity -= flushSize;
  868. if (dstCapacity < 4) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  869. LZ4F_writeLE32(dstPtr, 0);
  870. dstPtr += 4; /* endMark */
  871. if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
  872. U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
  873. if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  874. DEBUGLOG(5,"Writing 32-bit content checksum");
  875. LZ4F_writeLE32(dstPtr, xxh);
  876. dstPtr+=4; /* content Checksum */
  877. }
  878. cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
  879. cctxPtr->maxBufferSize = 0; /* reuse HC context */
  880. if (cctxPtr->prefs.frameInfo.contentSize) {
  881. if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
  882. return err0r(LZ4F_ERROR_frameSize_wrong);
  883. }
  884. return (size_t)(dstPtr - dstStart);
  885. }
  886. /*-***************************************************
  887. * Frame Decompression
  888. *****************************************************/
  889. typedef enum {
  890. dstage_getFrameHeader=0, dstage_storeFrameHeader,
  891. dstage_init,
  892. dstage_getBlockHeader, dstage_storeBlockHeader,
  893. dstage_copyDirect, dstage_getBlockChecksum,
  894. dstage_getCBlock, dstage_storeCBlock,
  895. dstage_flushOut,
  896. dstage_getSuffix, dstage_storeSuffix,
  897. dstage_getSFrameSize, dstage_storeSFrameSize,
  898. dstage_skipSkippable
  899. } dStage_t;
  900. struct LZ4F_dctx_s {
  901. LZ4F_frameInfo_t frameInfo;
  902. U32 version;
  903. dStage_t dStage;
  904. U64 frameRemainingSize;
  905. size_t maxBlockSize;
  906. size_t maxBufferSize;
  907. BYTE* tmpIn;
  908. size_t tmpInSize;
  909. size_t tmpInTarget;
  910. BYTE* tmpOutBuffer;
  911. const BYTE* dict;
  912. size_t dictSize;
  913. BYTE* tmpOut;
  914. size_t tmpOutSize;
  915. size_t tmpOutStart;
  916. XXH32_state_t xxh;
  917. XXH32_state_t blockChecksum;
  918. BYTE header[LZ4F_HEADER_SIZE_MAX];
  919. }; /* typedef'd to LZ4F_dctx in lz4frame.h */
  920. /*! LZ4F_createDecompressionContext() :
  921. * Create a decompressionContext object, which will track all decompression operations.
  922. * Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object.
  923. * Object can later be released using LZ4F_freeDecompressionContext().
  924. * @return : if != 0, there was an error during context creation.
  925. */
  926. LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)
  927. {
  928. LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOC_AND_ZERO(sizeof(LZ4F_dctx));
  929. if (dctx == NULL) { /* failed allocation */
  930. *LZ4F_decompressionContextPtr = NULL;
  931. return err0r(LZ4F_ERROR_allocation_failed);
  932. }
  933. dctx->version = versionNumber;
  934. *LZ4F_decompressionContextPtr = dctx;
  935. return LZ4F_OK_NoError;
  936. }
  937. LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx)
  938. {
  939. LZ4F_errorCode_t result = LZ4F_OK_NoError;
  940. if (dctx != NULL) { /* can accept NULL input, like free() */
  941. result = (LZ4F_errorCode_t)dctx->dStage;
  942. FREEMEM(dctx->tmpIn);
  943. FREEMEM(dctx->tmpOutBuffer);
  944. FREEMEM(dctx);
  945. }
  946. return result;
  947. }
  948. /*==--- Streaming Decompression operations ---==*/
  949. void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx)
  950. {
  951. dctx->dStage = dstage_getFrameHeader;
  952. dctx->dict = NULL;
  953. dctx->dictSize = 0;
  954. }
  955. /*! LZ4F_decodeHeader() :
  956. * input : `src` points at the **beginning of the frame**
  957. * output : set internal values of dctx, such as
  958. * dctx->frameInfo and dctx->dStage.
  959. * Also allocates internal buffers.
  960. * @return : nb Bytes read from src (necessarily <= srcSize)
  961. * or an error code (testable with LZ4F_isError())
  962. */
  963. static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize)
  964. {
  965. unsigned blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictIDFlag, blockSizeID;
  966. size_t frameHeaderSize;
  967. const BYTE* srcPtr = (const BYTE*)src;
  968. DEBUGLOG(5, "LZ4F_decodeHeader");
  969. /* need to decode header to get frameInfo */
  970. if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
  971. MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
  972. /* special case : skippable frames */
  973. if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {
  974. dctx->frameInfo.frameType = LZ4F_skippableFrame;
  975. if (src == (void*)(dctx->header)) {
  976. dctx->tmpInSize = srcSize;
  977. dctx->tmpInTarget = 8;
  978. dctx->dStage = dstage_storeSFrameSize;
  979. return srcSize;
  980. } else {
  981. dctx->dStage = dstage_getSFrameSize;
  982. return 4;
  983. }
  984. }
  985. /* control magic number */
  986. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  987. if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) {
  988. DEBUGLOG(4, "frame header error : unknown magic number");
  989. return err0r(LZ4F_ERROR_frameType_unknown);
  990. }
  991. #endif
  992. dctx->frameInfo.frameType = LZ4F_frame;
  993. /* Flags */
  994. { U32 const FLG = srcPtr[4];
  995. U32 const version = (FLG>>6) & _2BITS;
  996. blockChecksumFlag = (FLG>>4) & _1BIT;
  997. blockMode = (FLG>>5) & _1BIT;
  998. contentSizeFlag = (FLG>>3) & _1BIT;
  999. contentChecksumFlag = (FLG>>2) & _1BIT;
  1000. dictIDFlag = FLG & _1BIT;
  1001. /* validate */
  1002. if (((FLG>>1)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
  1003. if (version != 1) return err0r(LZ4F_ERROR_headerVersion_wrong); /* Version Number, only supported value */
  1004. }
  1005. /* Frame Header Size */
  1006. frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
  1007. if (srcSize < frameHeaderSize) {
  1008. /* not enough input to fully decode frame header */
  1009. if (srcPtr != dctx->header)
  1010. memcpy(dctx->header, srcPtr, srcSize);
  1011. dctx->tmpInSize = srcSize;
  1012. dctx->tmpInTarget = frameHeaderSize;
  1013. dctx->dStage = dstage_storeFrameHeader;
  1014. return srcSize;
  1015. }
  1016. { U32 const BD = srcPtr[5];
  1017. blockSizeID = (BD>>4) & _3BITS;
  1018. /* validate */
  1019. if (((BD>>7)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
  1020. if (blockSizeID < 4) return err0r(LZ4F_ERROR_maxBlockSize_invalid); /* 4-7 only supported values for the time being */
  1021. if (((BD>>0)&_4BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */
  1022. }
  1023. /* check header */
  1024. assert(frameHeaderSize > 5);
  1025. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1026. { BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
  1027. if (HC != srcPtr[frameHeaderSize-1])
  1028. return err0r(LZ4F_ERROR_headerChecksum_invalid);
  1029. }
  1030. #endif
  1031. /* save */
  1032. dctx->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;
  1033. dctx->frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)blockChecksumFlag;
  1034. dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag;
  1035. dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID;
  1036. dctx->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
  1037. if (contentSizeFlag)
  1038. dctx->frameRemainingSize =
  1039. dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6);
  1040. if (dictIDFlag)
  1041. dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5);
  1042. dctx->dStage = dstage_init;
  1043. return frameHeaderSize;
  1044. }
  1045. /*! LZ4F_headerSize() :
  1046. * @return : size of frame header
  1047. * or an error code, which can be tested using LZ4F_isError()
  1048. */
  1049. size_t LZ4F_headerSize(const void* src, size_t srcSize)
  1050. {
  1051. if (src == NULL) return err0r(LZ4F_ERROR_srcPtr_wrong);
  1052. /* minimal srcSize to determine header size */
  1053. if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH)
  1054. return err0r(LZ4F_ERROR_frameHeader_incomplete);
  1055. /* special case : skippable frames */
  1056. if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
  1057. return 8;
  1058. /* control magic number */
  1059. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1060. if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)
  1061. return err0r(LZ4F_ERROR_frameType_unknown);
  1062. #endif
  1063. /* Frame Header Size */
  1064. { BYTE const FLG = ((const BYTE*)src)[4];
  1065. U32 const contentSizeFlag = (FLG>>3) & _1BIT;
  1066. U32 const dictIDFlag = FLG & _1BIT;
  1067. return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
  1068. }
  1069. }
  1070. /*! LZ4F_getFrameInfo() :
  1071. * This function extracts frame parameters (max blockSize, frame checksum, etc.).
  1072. * Usage is optional. Objective is to provide relevant information for allocation purposes.
  1073. * This function works in 2 situations :
  1074. * - At the beginning of a new frame, in which case it will decode this information from `srcBuffer`, and start the decoding process.
  1075. * Amount of input data provided must be large enough to successfully decode the frame header.
  1076. * 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.
  1077. * - After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx.
  1078. * The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
  1079. * Decompression must resume from (srcBuffer + *srcSizePtr).
  1080. * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
  1081. * or an error code which can be tested using LZ4F_isError()
  1082. * note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped.
  1083. * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.
  1084. */
  1085. LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
  1086. LZ4F_frameInfo_t* frameInfoPtr,
  1087. const void* srcBuffer, size_t* srcSizePtr)
  1088. {
  1089. LZ4F_STATIC_ASSERT(dstage_getFrameHeader < dstage_storeFrameHeader);
  1090. if (dctx->dStage > dstage_storeFrameHeader) {
  1091. /* frameInfo already decoded */
  1092. size_t o=0, i=0;
  1093. *srcSizePtr = 0;
  1094. *frameInfoPtr = dctx->frameInfo;
  1095. /* returns : recommended nb of bytes for LZ4F_decompress() */
  1096. return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL);
  1097. } else {
  1098. if (dctx->dStage == dstage_storeFrameHeader) {
  1099. /* frame decoding already started, in the middle of header => automatic fail */
  1100. *srcSizePtr = 0;
  1101. return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted);
  1102. } else {
  1103. size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
  1104. if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
  1105. if (*srcSizePtr < hSize) {
  1106. *srcSizePtr=0;
  1107. return err0r(LZ4F_ERROR_frameHeader_incomplete);
  1108. }
  1109. { size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
  1110. if (LZ4F_isError(decodeResult)) {
  1111. *srcSizePtr = 0;
  1112. } else {
  1113. *srcSizePtr = decodeResult;
  1114. decodeResult = BHSize; /* block header size */
  1115. }
  1116. *frameInfoPtr = dctx->frameInfo;
  1117. return decodeResult;
  1118. } } }
  1119. }
  1120. /* LZ4F_updateDict() :
  1121. * only used for LZ4F_blockLinked mode
  1122. * Condition : dstPtr != NULL
  1123. */
  1124. static void LZ4F_updateDict(LZ4F_dctx* dctx,
  1125. const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,
  1126. unsigned withinTmp)
  1127. {
  1128. assert(dstPtr != NULL);
  1129. if (dctx->dictSize==0) {
  1130. dctx->dict = (const BYTE*)dstPtr; /* priority to prefix mode */
  1131. }
  1132. assert(dctx->dict != NULL);
  1133. if (dctx->dict + dctx->dictSize == dstPtr) { /* prefix mode, everything within dstBuffer */
  1134. dctx->dictSize += dstSize;
  1135. return;
  1136. }
  1137. assert(dstPtr >= dstBufferStart);
  1138. if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */
  1139. dctx->dict = (const BYTE*)dstBufferStart;
  1140. dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize;
  1141. return;
  1142. }
  1143. assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */
  1144. /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */
  1145. assert(dctx->tmpOutBuffer != NULL);
  1146. if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
  1147. /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */
  1148. assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);
  1149. dctx->dictSize += dstSize;
  1150. return;
  1151. }
  1152. if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
  1153. size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
  1154. size_t copySize = 64 KB - dctx->tmpOutSize;
  1155. const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
  1156. if (dctx->tmpOutSize > 64 KB) copySize = 0;
  1157. if (copySize > preserveSize) copySize = preserveSize;
  1158. memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
  1159. dctx->dict = dctx->tmpOutBuffer;
  1160. dctx->dictSize = preserveSize + dctx->tmpOutStart + dstSize;
  1161. return;
  1162. }
  1163. if (dctx->dict == dctx->tmpOutBuffer) { /* copy dst into tmp to complete dict */
  1164. if (dctx->dictSize + dstSize > dctx->maxBufferSize) { /* tmp buffer not large enough */
  1165. size_t const preserveSize = 64 KB - dstSize;
  1166. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
  1167. dctx->dictSize = preserveSize;
  1168. }
  1169. memcpy(dctx->tmpOutBuffer + dctx->dictSize, dstPtr, dstSize);
  1170. dctx->dictSize += dstSize;
  1171. return;
  1172. }
  1173. /* join dict & dest into tmp */
  1174. { size_t preserveSize = 64 KB - dstSize;
  1175. if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize;
  1176. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
  1177. memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize);
  1178. dctx->dict = dctx->tmpOutBuffer;
  1179. dctx->dictSize = preserveSize + dstSize;
  1180. }
  1181. }
  1182. /*! LZ4F_decompress() :
  1183. * Call this function repetitively to regenerate compressed data in srcBuffer.
  1184. * The function will attempt to decode up to *srcSizePtr bytes from srcBuffer
  1185. * into dstBuffer of capacity *dstSizePtr.
  1186. *
  1187. * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
  1188. *
  1189. * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
  1190. * If number of bytes read is < number of bytes provided, then decompression operation is not complete.
  1191. * Remaining data will have to be presented again in a subsequent invocation.
  1192. *
  1193. * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
  1194. * Schematically, it's the size of the current (or remaining) compressed block + header of next block.
  1195. * Respecting the hint provides a small boost to performance, since it allows less buffer shuffling.
  1196. * Note that this is just a hint, and it's always possible to any srcSize value.
  1197. * When a frame is fully decoded, @return will be 0.
  1198. * If decompression failed, @return is an error code which can be tested using LZ4F_isError().
  1199. */
  1200. size_t LZ4F_decompress(LZ4F_dctx* dctx,
  1201. void* dstBuffer, size_t* dstSizePtr,
  1202. const void* srcBuffer, size_t* srcSizePtr,
  1203. const LZ4F_decompressOptions_t* decompressOptionsPtr)
  1204. {
  1205. LZ4F_decompressOptions_t optionsNull;
  1206. const BYTE* const srcStart = (const BYTE*)srcBuffer;
  1207. const BYTE* const srcEnd = srcStart + *srcSizePtr;
  1208. const BYTE* srcPtr = srcStart;
  1209. BYTE* const dstStart = (BYTE*)dstBuffer;
  1210. BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL;
  1211. BYTE* dstPtr = dstStart;
  1212. const BYTE* selectedIn = NULL;
  1213. unsigned doAnotherStage = 1;
  1214. size_t nextSrcSizeHint = 1;
  1215. DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u",
  1216. srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr);
  1217. if (dstBuffer == NULL) assert(*dstSizePtr == 0);
  1218. MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
  1219. if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
  1220. *srcSizePtr = 0;
  1221. *dstSizePtr = 0;
  1222. assert(dctx != NULL);
  1223. /* behaves as a state machine */
  1224. while (doAnotherStage) {
  1225. switch(dctx->dStage)
  1226. {
  1227. case dstage_getFrameHeader:
  1228. DEBUGLOG(6, "dstage_getFrameHeader");
  1229. if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
  1230. size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */
  1231. if (LZ4F_isError(hSize)) return hSize;
  1232. srcPtr += hSize;
  1233. break;
  1234. }
  1235. dctx->tmpInSize = 0;
  1236. if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */
  1237. dctx->tmpInTarget = minFHSize; /* minimum size to decode header */
  1238. dctx->dStage = dstage_storeFrameHeader;
  1239. /* fall-through */
  1240. case dstage_storeFrameHeader:
  1241. DEBUGLOG(6, "dstage_storeFrameHeader");
  1242. { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));
  1243. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1244. dctx->tmpInSize += sizeToCopy;
  1245. srcPtr += sizeToCopy;
  1246. }
  1247. if (dctx->tmpInSize < dctx->tmpInTarget) {
  1248. nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
  1249. doAnotherStage = 0; /* not enough src data, ask for some more */
  1250. break;
  1251. }
  1252. { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
  1253. if (LZ4F_isError(hSize)) return hSize;
  1254. }
  1255. break;
  1256. case dstage_init:
  1257. DEBUGLOG(6, "dstage_init");
  1258. if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);
  1259. /* internal buffers allocation */
  1260. { size_t const bufferNeeded = dctx->maxBlockSize
  1261. + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0);
  1262. if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
  1263. dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
  1264. FREEMEM(dctx->tmpIn);
  1265. dctx->tmpIn = (BYTE*)ALLOC(dctx->maxBlockSize + BFSize /* block checksum */);
  1266. if (dctx->tmpIn == NULL)
  1267. return err0r(LZ4F_ERROR_allocation_failed);
  1268. FREEMEM(dctx->tmpOutBuffer);
  1269. dctx->tmpOutBuffer= (BYTE*)ALLOC(bufferNeeded);
  1270. if (dctx->tmpOutBuffer== NULL)
  1271. return err0r(LZ4F_ERROR_allocation_failed);
  1272. dctx->maxBufferSize = bufferNeeded;
  1273. } }
  1274. dctx->tmpInSize = 0;
  1275. dctx->tmpInTarget = 0;
  1276. dctx->tmpOut = dctx->tmpOutBuffer;
  1277. dctx->tmpOutStart = 0;
  1278. dctx->tmpOutSize = 0;
  1279. dctx->dStage = dstage_getBlockHeader;
  1280. /* fall-through */
  1281. case dstage_getBlockHeader:
  1282. if ((size_t)(srcEnd - srcPtr) >= BHSize) {
  1283. selectedIn = srcPtr;
  1284. srcPtr += BHSize;
  1285. } else {
  1286. /* not enough input to read cBlockSize field */
  1287. dctx->tmpInSize = 0;
  1288. dctx->dStage = dstage_storeBlockHeader;
  1289. }
  1290. if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */
  1291. case dstage_storeBlockHeader:
  1292. { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
  1293. size_t const wantedData = BHSize - dctx->tmpInSize;
  1294. size_t const sizeToCopy = MIN(wantedData, remainingInput);
  1295. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1296. srcPtr += sizeToCopy;
  1297. dctx->tmpInSize += sizeToCopy;
  1298. if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */
  1299. nextSrcSizeHint = BHSize - dctx->tmpInSize;
  1300. doAnotherStage = 0;
  1301. break;
  1302. }
  1303. selectedIn = dctx->tmpIn;
  1304. } /* if (dctx->dStage == dstage_storeBlockHeader) */
  1305. /* decode block header */
  1306. { U32 const blockHeader = LZ4F_readLE32(selectedIn);
  1307. size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU;
  1308. size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;
  1309. if (blockHeader==0) { /* frameEnd signal, no more block */
  1310. DEBUGLOG(5, "end of frame");
  1311. dctx->dStage = dstage_getSuffix;
  1312. break;
  1313. }
  1314. if (nextCBlockSize > dctx->maxBlockSize) {
  1315. return err0r(LZ4F_ERROR_maxBlockSize_invalid);
  1316. }
  1317. if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
  1318. /* next block is uncompressed */
  1319. dctx->tmpInTarget = nextCBlockSize;
  1320. DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize);
  1321. if (dctx->frameInfo.blockChecksumFlag) {
  1322. (void)XXH32_reset(&dctx->blockChecksum, 0);
  1323. }
  1324. dctx->dStage = dstage_copyDirect;
  1325. break;
  1326. }
  1327. /* next block is a compressed block */
  1328. dctx->tmpInTarget = nextCBlockSize + crcSize;
  1329. dctx->dStage = dstage_getCBlock;
  1330. if (dstPtr==dstEnd || srcPtr==srcEnd) {
  1331. nextSrcSizeHint = BHSize + nextCBlockSize + crcSize;
  1332. doAnotherStage = 0;
  1333. }
  1334. break;
  1335. }
  1336. case dstage_copyDirect: /* uncompressed block */
  1337. DEBUGLOG(6, "dstage_copyDirect");
  1338. { size_t sizeToCopy;
  1339. if (dstPtr == NULL) {
  1340. sizeToCopy = 0;
  1341. } else {
  1342. size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
  1343. sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
  1344. memcpy(dstPtr, srcPtr, sizeToCopy);
  1345. if (dctx->frameInfo.blockChecksumFlag) {
  1346. (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
  1347. }
  1348. if (dctx->frameInfo.contentChecksumFlag)
  1349. (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
  1350. if (dctx->frameInfo.contentSize)
  1351. dctx->frameRemainingSize -= sizeToCopy;
  1352. /* history management (linked blocks only)*/
  1353. if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
  1354. LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
  1355. } }
  1356. srcPtr += sizeToCopy;
  1357. dstPtr += sizeToCopy;
  1358. if (sizeToCopy == dctx->tmpInTarget) { /* all done */
  1359. if (dctx->frameInfo.blockChecksumFlag) {
  1360. dctx->tmpInSize = 0;
  1361. dctx->dStage = dstage_getBlockChecksum;
  1362. } else
  1363. dctx->dStage = dstage_getBlockHeader; /* new block */
  1364. break;
  1365. }
  1366. dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
  1367. }
  1368. nextSrcSizeHint = dctx->tmpInTarget +
  1369. +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
  1370. + BHSize /* next header size */;
  1371. doAnotherStage = 0;
  1372. break;
  1373. /* check block checksum for recently transferred uncompressed block */
  1374. case dstage_getBlockChecksum:
  1375. DEBUGLOG(6, "dstage_getBlockChecksum");
  1376. { const void* crcSrc;
  1377. if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {
  1378. crcSrc = srcPtr;
  1379. srcPtr += 4;
  1380. } else {
  1381. size_t const stillToCopy = 4 - dctx->tmpInSize;
  1382. size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr));
  1383. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1384. dctx->tmpInSize += sizeToCopy;
  1385. srcPtr += sizeToCopy;
  1386. if (dctx->tmpInSize < 4) { /* all input consumed */
  1387. doAnotherStage = 0;
  1388. break;
  1389. }
  1390. crcSrc = dctx->header;
  1391. }
  1392. { U32 const readCRC = LZ4F_readLE32(crcSrc);
  1393. U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
  1394. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1395. DEBUGLOG(6, "compare block checksum");
  1396. if (readCRC != calcCRC) {
  1397. DEBUGLOG(4, "incorrect block checksum: %08X != %08X",
  1398. readCRC, calcCRC);
  1399. return err0r(LZ4F_ERROR_blockChecksum_invalid);
  1400. }
  1401. #else
  1402. (void)readCRC;
  1403. (void)calcCRC;
  1404. #endif
  1405. } }
  1406. dctx->dStage = dstage_getBlockHeader; /* new block */
  1407. break;
  1408. case dstage_getCBlock:
  1409. DEBUGLOG(6, "dstage_getCBlock");
  1410. if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
  1411. dctx->tmpInSize = 0;
  1412. dctx->dStage = dstage_storeCBlock;
  1413. break;
  1414. }
  1415. /* input large enough to read full block directly */
  1416. selectedIn = srcPtr;
  1417. srcPtr += dctx->tmpInTarget;
  1418. if (0) /* always jump over next block */
  1419. case dstage_storeCBlock:
  1420. { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
  1421. size_t const inputLeft = (size_t)(srcEnd-srcPtr);
  1422. size_t const sizeToCopy = MIN(wantedData, inputLeft);
  1423. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1424. dctx->tmpInSize += sizeToCopy;
  1425. srcPtr += sizeToCopy;
  1426. if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */
  1427. nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize)
  1428. + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
  1429. + BHSize /* next header size */;
  1430. doAnotherStage = 0;
  1431. break;
  1432. }
  1433. selectedIn = dctx->tmpIn;
  1434. }
  1435. /* At this stage, input is large enough to decode a block */
  1436. if (dctx->frameInfo.blockChecksumFlag) {
  1437. dctx->tmpInTarget -= 4;
  1438. assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */
  1439. { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);
  1440. U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);
  1441. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1442. if (readBlockCrc != calcBlockCrc)
  1443. return err0r(LZ4F_ERROR_blockChecksum_invalid);
  1444. #else
  1445. (void)readBlockCrc;
  1446. (void)calcBlockCrc;
  1447. #endif
  1448. } }
  1449. if ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize) {
  1450. const char* dict = (const char*)dctx->dict;
  1451. size_t dictSize = dctx->dictSize;
  1452. int decodedSize;
  1453. assert(dstPtr != NULL);
  1454. if (dict && dictSize > 1 GB) {
  1455. /* the dictSize param is an int, avoid truncation / sign issues */
  1456. dict += dictSize - 64 KB;
  1457. dictSize = 64 KB;
  1458. }
  1459. /* enough capacity in `dst` to decompress directly there */
  1460. decodedSize = LZ4_decompress_safe_usingDict(
  1461. (const char*)selectedIn, (char*)dstPtr,
  1462. (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
  1463. dict, (int)dictSize);
  1464. if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
  1465. if (dctx->frameInfo.contentChecksumFlag)
  1466. XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize);
  1467. if (dctx->frameInfo.contentSize)
  1468. dctx->frameRemainingSize -= (size_t)decodedSize;
  1469. /* dictionary management */
  1470. if (dctx->frameInfo.blockMode==LZ4F_blockLinked) {
  1471. LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
  1472. }
  1473. dstPtr += decodedSize;
  1474. dctx->dStage = dstage_getBlockHeader;
  1475. break;
  1476. }
  1477. /* not enough place into dst : decode into tmpOut */
  1478. /* ensure enough place for tmpOut */
  1479. if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
  1480. if (dctx->dict == dctx->tmpOutBuffer) {
  1481. if (dctx->dictSize > 128 KB) {
  1482. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB);
  1483. dctx->dictSize = 64 KB;
  1484. }
  1485. dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize;
  1486. } else { /* dict not within tmp */
  1487. size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);
  1488. dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;
  1489. } }
  1490. /* Decode block */
  1491. { const char* dict = (const char*)dctx->dict;
  1492. size_t dictSize = dctx->dictSize;
  1493. int decodedSize;
  1494. if (dict && dictSize > 1 GB) {
  1495. /* the dictSize param is an int, avoid truncation / sign issues */
  1496. dict += dictSize - 64 KB;
  1497. dictSize = 64 KB;
  1498. }
  1499. decodedSize = LZ4_decompress_safe_usingDict(
  1500. (const char*)selectedIn, (char*)dctx->tmpOut,
  1501. (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
  1502. dict, (int)dictSize);
  1503. if (decodedSize < 0) /* decompression failed */
  1504. return err0r(LZ4F_ERROR_decompressionFailed);
  1505. if (dctx->frameInfo.contentChecksumFlag)
  1506. XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize);
  1507. if (dctx->frameInfo.contentSize)
  1508. dctx->frameRemainingSize -= (size_t)decodedSize;
  1509. dctx->tmpOutSize = (size_t)decodedSize;
  1510. dctx->tmpOutStart = 0;
  1511. dctx->dStage = dstage_flushOut;
  1512. }
  1513. /* fall-through */
  1514. case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
  1515. DEBUGLOG(6, "dstage_flushOut");
  1516. if (dstPtr != NULL) {
  1517. size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
  1518. memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
  1519. /* dictionary management */
  1520. if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
  1521. LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/);
  1522. dctx->tmpOutStart += sizeToCopy;
  1523. dstPtr += sizeToCopy;
  1524. }
  1525. if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
  1526. dctx->dStage = dstage_getBlockHeader; /* get next block */
  1527. break;
  1528. }
  1529. /* could not flush everything : stop there, just request a block header */
  1530. doAnotherStage = 0;
  1531. nextSrcSizeHint = BHSize;
  1532. break;
  1533. case dstage_getSuffix:
  1534. if (dctx->frameRemainingSize)
  1535. return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
  1536. if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */
  1537. nextSrcSizeHint = 0;
  1538. LZ4F_resetDecompressionContext(dctx);
  1539. doAnotherStage = 0;
  1540. break;
  1541. }
  1542. if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
  1543. dctx->tmpInSize = 0;
  1544. dctx->dStage = dstage_storeSuffix;
  1545. } else {
  1546. selectedIn = srcPtr;
  1547. srcPtr += 4;
  1548. }
  1549. if (dctx->dStage == dstage_storeSuffix) /* can be skipped */
  1550. case dstage_storeSuffix:
  1551. { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
  1552. size_t const wantedData = 4 - dctx->tmpInSize;
  1553. size_t const sizeToCopy = MIN(wantedData, remainingInput);
  1554. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1555. srcPtr += sizeToCopy;
  1556. dctx->tmpInSize += sizeToCopy;
  1557. if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */
  1558. nextSrcSizeHint = 4 - dctx->tmpInSize;
  1559. doAnotherStage=0;
  1560. break;
  1561. }
  1562. selectedIn = dctx->tmpIn;
  1563. } /* if (dctx->dStage == dstage_storeSuffix) */
  1564. /* case dstage_checkSuffix: */ /* no direct entry, avoid initialization risks */
  1565. { U32 const readCRC = LZ4F_readLE32(selectedIn);
  1566. U32 const resultCRC = XXH32_digest(&(dctx->xxh));
  1567. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1568. if (readCRC != resultCRC)
  1569. return err0r(LZ4F_ERROR_contentChecksum_invalid);
  1570. #else
  1571. (void)readCRC;
  1572. (void)resultCRC;
  1573. #endif
  1574. nextSrcSizeHint = 0;
  1575. LZ4F_resetDecompressionContext(dctx);
  1576. doAnotherStage = 0;
  1577. break;
  1578. }
  1579. case dstage_getSFrameSize:
  1580. if ((srcEnd - srcPtr) >= 4) {
  1581. selectedIn = srcPtr;
  1582. srcPtr += 4;
  1583. } else {
  1584. /* not enough input to read cBlockSize field */
  1585. dctx->tmpInSize = 4;
  1586. dctx->tmpInTarget = 8;
  1587. dctx->dStage = dstage_storeSFrameSize;
  1588. }
  1589. if (dctx->dStage == dstage_storeSFrameSize)
  1590. case dstage_storeSFrameSize:
  1591. { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
  1592. (size_t)(srcEnd - srcPtr) );
  1593. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1594. srcPtr += sizeToCopy;
  1595. dctx->tmpInSize += sizeToCopy;
  1596. if (dctx->tmpInSize < dctx->tmpInTarget) {
  1597. /* not enough input to get full sBlockSize; wait for more */
  1598. nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize;
  1599. doAnotherStage = 0;
  1600. break;
  1601. }
  1602. selectedIn = dctx->header + 4;
  1603. } /* if (dctx->dStage == dstage_storeSFrameSize) */
  1604. /* case dstage_decodeSFrameSize: */ /* no direct entry */
  1605. { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
  1606. dctx->frameInfo.contentSize = SFrameSize;
  1607. dctx->tmpInTarget = SFrameSize;
  1608. dctx->dStage = dstage_skipSkippable;
  1609. break;
  1610. }
  1611. case dstage_skipSkippable:
  1612. { size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr));
  1613. srcPtr += skipSize;
  1614. dctx->tmpInTarget -= skipSize;
  1615. doAnotherStage = 0;
  1616. nextSrcSizeHint = dctx->tmpInTarget;
  1617. if (nextSrcSizeHint) break; /* still more to skip */
  1618. /* frame fully skipped : prepare context for a new frame */
  1619. LZ4F_resetDecompressionContext(dctx);
  1620. break;
  1621. }
  1622. } /* switch (dctx->dStage) */
  1623. } /* while (doAnotherStage) */
  1624. /* preserve history within tmp whenever necessary */
  1625. LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);
  1626. if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */
  1627. && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */
  1628. && (dctx->dict != NULL) /* dictionary exists */
  1629. && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */
  1630. && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
  1631. {
  1632. if (dctx->dStage == dstage_flushOut) {
  1633. size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
  1634. size_t copySize = 64 KB - dctx->tmpOutSize;
  1635. const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
  1636. if (dctx->tmpOutSize > 64 KB) copySize = 0;
  1637. if (copySize > preserveSize) copySize = preserveSize;
  1638. assert(dctx->tmpOutBuffer != NULL);
  1639. memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
  1640. dctx->dict = dctx->tmpOutBuffer;
  1641. dctx->dictSize = preserveSize + dctx->tmpOutStart;
  1642. } else {
  1643. const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
  1644. size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
  1645. memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
  1646. dctx->dict = dctx->tmpOutBuffer;
  1647. dctx->dictSize = newDictSize;
  1648. dctx->tmpOut = dctx->tmpOutBuffer + newDictSize;
  1649. }
  1650. }
  1651. *srcSizePtr = (size_t)(srcPtr - srcStart);
  1652. *dstSizePtr = (size_t)(dstPtr - dstStart);
  1653. return nextSrcSizeHint;
  1654. }
  1655. /*! LZ4F_decompress_usingDict() :
  1656. * Same as LZ4F_decompress(), using a predefined dictionary.
  1657. * Dictionary is used "in place", without any preprocessing.
  1658. * It must remain accessible throughout the entire frame decoding.
  1659. */
  1660. size_t LZ4F_decompress_usingDict(LZ4F_dctx* dctx,
  1661. void* dstBuffer, size_t* dstSizePtr,
  1662. const void* srcBuffer, size_t* srcSizePtr,
  1663. const void* dict, size_t dictSize,
  1664. const LZ4F_decompressOptions_t* decompressOptionsPtr)
  1665. {
  1666. if (dctx->dStage <= dstage_init) {
  1667. dctx->dict = (const BYTE*)dict;
  1668. dctx->dictSize = dictSize;
  1669. }
  1670. return LZ4F_decompress(dctx, dstBuffer, dstSizePtr,
  1671. srcBuffer, srcSizePtr,
  1672. decompressOptionsPtr);
  1673. }