lz4frame.c 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  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. #include <stdlib.h> /* malloc, calloc, free */
  68. #ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */
  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_compressionContext_t* 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 = (LZ4F_compressionContext_t)cctxPtr;
  471. return LZ4F_OK_NoError;
  472. }
  473. LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
  474. {
  475. LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
  476. if (cctxPtr != NULL) { /* support free on NULL */
  477. FREEMEM(cctxPtr->lz4CtxPtr); /* works because LZ4_streamHC_t and LZ4_stream_t are simple POD types */
  478. FREEMEM(cctxPtr->tmpBuff);
  479. FREEMEM(LZ4F_compressionContext);
  480. }
  481. return LZ4F_OK_NoError;
  482. }
  483. /**
  484. * This function prepares the internal LZ4(HC) stream for a new compression,
  485. * resetting the context and attaching the dictionary, if there is one.
  486. *
  487. * It needs to be called at the beginning of each independent compression
  488. * stream (i.e., at the beginning of a frame in blockLinked mode, or at the
  489. * beginning of each block in blockIndependent mode).
  490. */
  491. static void LZ4F_initStream(void* ctx,
  492. const LZ4F_CDict* cdict,
  493. int level,
  494. LZ4F_blockMode_t blockMode) {
  495. if (level < LZ4HC_CLEVEL_MIN) {
  496. if (cdict != NULL || blockMode == LZ4F_blockLinked) {
  497. /* In these cases, we will call LZ4_compress_fast_continue(),
  498. * which needs an already reset context. Otherwise, we'll call a
  499. * one-shot API. The non-continued APIs internally perform their own
  500. * resets at the beginning of their calls, where they know what
  501. * tableType they need the context to be in. So in that case this
  502. * would be misguided / wasted work. */
  503. LZ4_resetStream_fast((LZ4_stream_t*)ctx);
  504. }
  505. LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL);
  506. } else {
  507. LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level);
  508. LZ4_attach_HC_dictionary((LZ4_streamHC_t *)ctx, cdict ? cdict->HCCtx : NULL);
  509. }
  510. }
  511. /*! LZ4F_compressBegin_usingCDict() :
  512. * init streaming compression and writes frame header into dstBuffer.
  513. * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
  514. * @return : number of bytes written into dstBuffer for the header
  515. * or an error code (can be tested using LZ4F_isError())
  516. */
  517. size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr,
  518. void* dstBuffer, size_t dstCapacity,
  519. const LZ4F_CDict* cdict,
  520. const LZ4F_preferences_t* preferencesPtr)
  521. {
  522. LZ4F_preferences_t prefNull;
  523. BYTE* const dstStart = (BYTE*)dstBuffer;
  524. BYTE* dstPtr = dstStart;
  525. BYTE* headerStart;
  526. if (dstCapacity < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  527. MEM_INIT(&prefNull, 0, sizeof(prefNull));
  528. if (preferencesPtr == NULL) preferencesPtr = &prefNull;
  529. cctxPtr->prefs = *preferencesPtr;
  530. /* Ctx Management */
  531. { U16 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2;
  532. if (cctxPtr->lz4CtxAlloc < ctxTypeID) {
  533. FREEMEM(cctxPtr->lz4CtxPtr);
  534. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
  535. cctxPtr->lz4CtxPtr = LZ4_createStream();
  536. } else {
  537. cctxPtr->lz4CtxPtr = LZ4_createStreamHC();
  538. }
  539. if (cctxPtr->lz4CtxPtr == NULL)
  540. return err0r(LZ4F_ERROR_allocation_failed);
  541. cctxPtr->lz4CtxAlloc = ctxTypeID;
  542. cctxPtr->lz4CtxState = ctxTypeID;
  543. } else if (cctxPtr->lz4CtxState != ctxTypeID) {
  544. /* otherwise, a sufficient buffer is allocated, but we need to
  545. * reset it to the correct context type */
  546. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {
  547. LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t));
  548. } else {
  549. LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t));
  550. LZ4_setCompressionLevel((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel);
  551. }
  552. cctxPtr->lz4CtxState = ctxTypeID;
  553. }
  554. }
  555. /* Buffer Management */
  556. if (cctxPtr->prefs.frameInfo.blockSizeID == 0)
  557. cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;
  558. cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);
  559. { size_t const requiredBuffSize = preferencesPtr->autoFlush ?
  560. ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */
  561. cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0);
  562. if (cctxPtr->maxBufferSize < requiredBuffSize) {
  563. cctxPtr->maxBufferSize = 0;
  564. FREEMEM(cctxPtr->tmpBuff);
  565. cctxPtr->tmpBuff = (BYTE*)ALLOC_AND_ZERO(requiredBuffSize);
  566. if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed);
  567. cctxPtr->maxBufferSize = requiredBuffSize;
  568. } }
  569. cctxPtr->tmpIn = cctxPtr->tmpBuff;
  570. cctxPtr->tmpInSize = 0;
  571. (void)XXH32_reset(&(cctxPtr->xxh), 0);
  572. /* context init */
  573. cctxPtr->cdict = cdict;
  574. if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) {
  575. /* frame init only for blockLinked : blockIndependent will be init at each block */
  576. LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked);
  577. }
  578. if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) {
  579. LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed);
  580. }
  581. /* Magic Number */
  582. LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);
  583. dstPtr += 4;
  584. headerStart = dstPtr;
  585. /* FLG Byte */
  586. *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */
  587. + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)
  588. + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4)
  589. + ((unsigned)(cctxPtr->prefs.frameInfo.contentSize > 0) << 3)
  590. + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)
  591. + (cctxPtr->prefs.frameInfo.dictID > 0) );
  592. /* BD Byte */
  593. *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);
  594. /* Optional Frame content size field */
  595. if (cctxPtr->prefs.frameInfo.contentSize) {
  596. LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);
  597. dstPtr += 8;
  598. cctxPtr->totalInSize = 0;
  599. }
  600. /* Optional dictionary ID field */
  601. if (cctxPtr->prefs.frameInfo.dictID) {
  602. LZ4F_writeLE32(dstPtr, cctxPtr->prefs.frameInfo.dictID);
  603. dstPtr += 4;
  604. }
  605. /* Header CRC Byte */
  606. *dstPtr = LZ4F_headerChecksum(headerStart, (size_t)(dstPtr - headerStart));
  607. dstPtr++;
  608. cctxPtr->cStage = 1; /* header written, now request input data block */
  609. return (size_t)(dstPtr - dstStart);
  610. }
  611. /*! LZ4F_compressBegin() :
  612. * init streaming compression and writes frame header into dstBuffer.
  613. * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes.
  614. * preferencesPtr can be NULL, in which case default parameters are selected.
  615. * @return : number of bytes written into dstBuffer for the header
  616. * or an error code (can be tested using LZ4F_isError())
  617. */
  618. size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr,
  619. void* dstBuffer, size_t dstCapacity,
  620. const LZ4F_preferences_t* preferencesPtr)
  621. {
  622. return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity,
  623. NULL, preferencesPtr);
  624. }
  625. /* LZ4F_compressBound() :
  626. * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario.
  627. * LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario.
  628. * This function cannot fail.
  629. */
  630. size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)
  631. {
  632. return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);
  633. }
  634. typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level, const LZ4F_CDict* cdict);
  635. /*! LZ4F_makeBlock():
  636. * compress a single block, add header and optional checksum.
  637. * assumption : dst buffer capacity is >= BHSize + srcSize + crcSize
  638. */
  639. static size_t LZ4F_makeBlock(void* dst,
  640. const void* src, size_t srcSize,
  641. compressFunc_t compress, void* lz4ctx, int level,
  642. const LZ4F_CDict* cdict,
  643. LZ4F_blockChecksum_t crcFlag)
  644. {
  645. BYTE* const cSizePtr = (BYTE*)dst;
  646. U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+BHSize),
  647. (int)(srcSize), (int)(srcSize-1),
  648. level, cdict);
  649. if (cSize == 0) { /* compression failed */
  650. cSize = (U32)srcSize;
  651. LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);
  652. memcpy(cSizePtr+BHSize, src, srcSize);
  653. } else {
  654. LZ4F_writeLE32(cSizePtr, cSize);
  655. }
  656. if (crcFlag) {
  657. U32 const crc32 = XXH32(cSizePtr+BHSize, cSize, 0); /* checksum of compressed data */
  658. LZ4F_writeLE32(cSizePtr+BHSize+cSize, crc32);
  659. }
  660. return BHSize + cSize + ((U32)crcFlag)*BFSize;
  661. }
  662. static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  663. {
  664. int const acceleration = (level < 0) ? -level + 1 : 1;
  665. LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
  666. if (cdict) {
  667. return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
  668. } else {
  669. return LZ4_compress_fast_extState_fastReset(ctx, src, dst, srcSize, dstCapacity, acceleration);
  670. }
  671. }
  672. static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  673. {
  674. int const acceleration = (level < 0) ? -level + 1 : 1;
  675. (void)cdict; /* init once at beginning of frame */
  676. return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);
  677. }
  678. static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  679. {
  680. LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);
  681. if (cdict) {
  682. return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
  683. }
  684. return LZ4_compress_HC_extStateHC_fastReset(ctx, src, dst, srcSize, dstCapacity, level);
  685. }
  686. static int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)
  687. {
  688. (void)level; (void)cdict; /* init once at beginning of frame */
  689. return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);
  690. }
  691. static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level)
  692. {
  693. if (level < LZ4HC_CLEVEL_MIN) {
  694. if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock;
  695. return LZ4F_compressBlock_continue;
  696. }
  697. if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlockHC;
  698. return LZ4F_compressBlockHC_continue;
  699. }
  700. static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)
  701. {
  702. if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)
  703. return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
  704. return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);
  705. }
  706. typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;
  707. /*! LZ4F_compressUpdate() :
  708. * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
  709. * dstBuffer MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).
  710. * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
  711. * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.
  712. * or an error code if it fails (which can be tested using LZ4F_isError())
  713. */
  714. size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,
  715. void* dstBuffer, size_t dstCapacity,
  716. const void* srcBuffer, size_t srcSize,
  717. const LZ4F_compressOptions_t* compressOptionsPtr)
  718. {
  719. LZ4F_compressOptions_t cOptionsNull;
  720. size_t const blockSize = cctxPtr->maxBlockSize;
  721. const BYTE* srcPtr = (const BYTE*)srcBuffer;
  722. const BYTE* const srcEnd = srcPtr + srcSize;
  723. BYTE* const dstStart = (BYTE*)dstBuffer;
  724. BYTE* dstPtr = dstStart;
  725. LZ4F_lastBlockStatus lastBlockCompressed = notDone;
  726. compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
  727. DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize);
  728. if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
  729. if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))
  730. return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  731. MEM_INIT(&cOptionsNull, 0, sizeof(cOptionsNull));
  732. if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;
  733. /* complete tmp buffer */
  734. if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */
  735. size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;
  736. if (sizeToCopy > srcSize) {
  737. /* add src to tmpIn buffer */
  738. memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);
  739. srcPtr = srcEnd;
  740. cctxPtr->tmpInSize += srcSize;
  741. /* still needs some CRC */
  742. } else {
  743. /* complete tmpIn block and then compress it */
  744. lastBlockCompressed = fromTmpBuffer;
  745. memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);
  746. srcPtr += sizeToCopy;
  747. dstPtr += LZ4F_makeBlock(dstPtr,
  748. cctxPtr->tmpIn, blockSize,
  749. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  750. cctxPtr->cdict,
  751. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  752. if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;
  753. cctxPtr->tmpInSize = 0;
  754. }
  755. }
  756. while ((size_t)(srcEnd - srcPtr) >= blockSize) {
  757. /* compress full blocks */
  758. lastBlockCompressed = fromSrcBuffer;
  759. dstPtr += LZ4F_makeBlock(dstPtr,
  760. srcPtr, blockSize,
  761. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  762. cctxPtr->cdict,
  763. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  764. srcPtr += blockSize;
  765. }
  766. if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {
  767. /* compress remaining input < blockSize */
  768. lastBlockCompressed = fromSrcBuffer;
  769. dstPtr += LZ4F_makeBlock(dstPtr,
  770. srcPtr, (size_t)(srcEnd - srcPtr),
  771. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  772. cctxPtr->cdict,
  773. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  774. srcPtr = srcEnd;
  775. }
  776. /* preserve dictionary if necessary */
  777. if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {
  778. if (compressOptionsPtr->stableSrc) {
  779. cctxPtr->tmpIn = cctxPtr->tmpBuff;
  780. } else {
  781. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  782. if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC);
  783. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  784. }
  785. }
  786. /* keep tmpIn within limits */
  787. if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */
  788. && !(cctxPtr->prefs.autoFlush))
  789. {
  790. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  791. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  792. }
  793. /* some input data left, necessarily < blockSize */
  794. if (srcPtr < srcEnd) {
  795. /* fill tmp buffer */
  796. size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);
  797. memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);
  798. cctxPtr->tmpInSize = sizeToCopy;
  799. }
  800. if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)
  801. (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);
  802. cctxPtr->totalInSize += srcSize;
  803. return (size_t)(dstPtr - dstStart);
  804. }
  805. /*! LZ4F_flush() :
  806. * When compressed data must be sent immediately, without waiting for a block to be filled,
  807. * invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx.
  808. * The result of the function is the number of bytes written into dstBuffer.
  809. * It can be zero, this means there was no data left within LZ4F_cctx.
  810. * The function outputs an error code if it fails (can be tested using LZ4F_isError())
  811. * LZ4F_compressOptions_t* is optional. NULL is a valid argument.
  812. */
  813. size_t LZ4F_flush(LZ4F_cctx* cctxPtr,
  814. void* dstBuffer, size_t dstCapacity,
  815. const LZ4F_compressOptions_t* compressOptionsPtr)
  816. {
  817. BYTE* const dstStart = (BYTE*)dstBuffer;
  818. BYTE* dstPtr = dstStart;
  819. compressFunc_t compress;
  820. if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
  821. if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC);
  822. if (dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize))
  823. return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  824. (void)compressOptionsPtr; /* not yet useful */
  825. /* select compression function */
  826. compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);
  827. /* compress tmp buffer */
  828. dstPtr += LZ4F_makeBlock(dstPtr,
  829. cctxPtr->tmpIn, cctxPtr->tmpInSize,
  830. compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,
  831. cctxPtr->cdict,
  832. cctxPtr->prefs.frameInfo.blockChecksumFlag);
  833. assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity));
  834. if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)
  835. cctxPtr->tmpIn += cctxPtr->tmpInSize;
  836. cctxPtr->tmpInSize = 0;
  837. /* keep tmpIn within limits */
  838. if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */
  839. int const realDictSize = LZ4F_localSaveDict(cctxPtr);
  840. cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
  841. }
  842. return (size_t)(dstPtr - dstStart);
  843. }
  844. /*! LZ4F_compressEnd() :
  845. * When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
  846. * It will flush whatever data remained within compressionContext (like LZ4_flush())
  847. * but also properly finalize the frame, with an endMark and an (optional) checksum.
  848. * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
  849. * @return: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
  850. * or an error code if it fails (can be tested using LZ4F_isError())
  851. * The context can then be used again to compress a new frame, starting with LZ4F_compressBegin().
  852. */
  853. size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,
  854. void* dstBuffer, size_t dstCapacity,
  855. const LZ4F_compressOptions_t* compressOptionsPtr)
  856. {
  857. BYTE* const dstStart = (BYTE*)dstBuffer;
  858. BYTE* dstPtr = dstStart;
  859. size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);
  860. if (LZ4F_isError(flushSize)) return flushSize;
  861. dstPtr += flushSize;
  862. assert(flushSize <= dstCapacity);
  863. dstCapacity -= flushSize;
  864. if (dstCapacity < 4) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  865. LZ4F_writeLE32(dstPtr, 0);
  866. dstPtr += 4; /* endMark */
  867. if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {
  868. U32 const xxh = XXH32_digest(&(cctxPtr->xxh));
  869. if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall);
  870. LZ4F_writeLE32(dstPtr, xxh);
  871. dstPtr+=4; /* content Checksum */
  872. }
  873. cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */
  874. cctxPtr->maxBufferSize = 0; /* reuse HC context */
  875. if (cctxPtr->prefs.frameInfo.contentSize) {
  876. if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)
  877. return err0r(LZ4F_ERROR_frameSize_wrong);
  878. }
  879. return (size_t)(dstPtr - dstStart);
  880. }
  881. /*-***************************************************
  882. * Frame Decompression
  883. *****************************************************/
  884. typedef enum {
  885. dstage_getFrameHeader=0, dstage_storeFrameHeader,
  886. dstage_init,
  887. dstage_getBlockHeader, dstage_storeBlockHeader,
  888. dstage_copyDirect, dstage_getBlockChecksum,
  889. dstage_getCBlock, dstage_storeCBlock,
  890. dstage_flushOut,
  891. dstage_getSuffix, dstage_storeSuffix,
  892. dstage_getSFrameSize, dstage_storeSFrameSize,
  893. dstage_skipSkippable
  894. } dStage_t;
  895. struct LZ4F_dctx_s {
  896. LZ4F_frameInfo_t frameInfo;
  897. U32 version;
  898. dStage_t dStage;
  899. U64 frameRemainingSize;
  900. size_t maxBlockSize;
  901. size_t maxBufferSize;
  902. BYTE* tmpIn;
  903. size_t tmpInSize;
  904. size_t tmpInTarget;
  905. BYTE* tmpOutBuffer;
  906. const BYTE* dict;
  907. size_t dictSize;
  908. BYTE* tmpOut;
  909. size_t tmpOutSize;
  910. size_t tmpOutStart;
  911. XXH32_state_t xxh;
  912. XXH32_state_t blockChecksum;
  913. BYTE header[LZ4F_HEADER_SIZE_MAX];
  914. }; /* typedef'd to LZ4F_dctx in lz4frame.h */
  915. /*! LZ4F_createDecompressionContext() :
  916. * Create a decompressionContext object, which will track all decompression operations.
  917. * Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object.
  918. * Object can later be released using LZ4F_freeDecompressionContext().
  919. * @return : if != 0, there was an error during context creation.
  920. */
  921. LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)
  922. {
  923. LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOC_AND_ZERO(sizeof(LZ4F_dctx));
  924. if (dctx == NULL) { /* failed allocation */
  925. *LZ4F_decompressionContextPtr = NULL;
  926. return err0r(LZ4F_ERROR_allocation_failed);
  927. }
  928. dctx->version = versionNumber;
  929. *LZ4F_decompressionContextPtr = dctx;
  930. return LZ4F_OK_NoError;
  931. }
  932. LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx)
  933. {
  934. LZ4F_errorCode_t result = LZ4F_OK_NoError;
  935. if (dctx != NULL) { /* can accept NULL input, like free() */
  936. result = (LZ4F_errorCode_t)dctx->dStage;
  937. FREEMEM(dctx->tmpIn);
  938. FREEMEM(dctx->tmpOutBuffer);
  939. FREEMEM(dctx);
  940. }
  941. return result;
  942. }
  943. /*==--- Streaming Decompression operations ---==*/
  944. void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx)
  945. {
  946. dctx->dStage = dstage_getFrameHeader;
  947. dctx->dict = NULL;
  948. dctx->dictSize = 0;
  949. }
  950. /*! LZ4F_decodeHeader() :
  951. * input : `src` points at the **beginning of the frame**
  952. * output : set internal values of dctx, such as
  953. * dctx->frameInfo and dctx->dStage.
  954. * Also allocates internal buffers.
  955. * @return : nb Bytes read from src (necessarily <= srcSize)
  956. * or an error code (testable with LZ4F_isError())
  957. */
  958. static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize)
  959. {
  960. unsigned blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictIDFlag, blockSizeID;
  961. size_t frameHeaderSize;
  962. const BYTE* srcPtr = (const BYTE*)src;
  963. /* need to decode header to get frameInfo */
  964. if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */
  965. MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));
  966. /* special case : skippable frames */
  967. if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {
  968. dctx->frameInfo.frameType = LZ4F_skippableFrame;
  969. if (src == (void*)(dctx->header)) {
  970. dctx->tmpInSize = srcSize;
  971. dctx->tmpInTarget = 8;
  972. dctx->dStage = dstage_storeSFrameSize;
  973. return srcSize;
  974. } else {
  975. dctx->dStage = dstage_getSFrameSize;
  976. return 4;
  977. }
  978. }
  979. /* control magic number */
  980. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  981. if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER)
  982. return err0r(LZ4F_ERROR_frameType_unknown);
  983. #endif
  984. dctx->frameInfo.frameType = LZ4F_frame;
  985. /* Flags */
  986. { U32 const FLG = srcPtr[4];
  987. U32 const version = (FLG>>6) & _2BITS;
  988. blockChecksumFlag = (FLG>>4) & _1BIT;
  989. blockMode = (FLG>>5) & _1BIT;
  990. contentSizeFlag = (FLG>>3) & _1BIT;
  991. contentChecksumFlag = (FLG>>2) & _1BIT;
  992. dictIDFlag = FLG & _1BIT;
  993. /* validate */
  994. if (((FLG>>1)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
  995. if (version != 1) return err0r(LZ4F_ERROR_headerVersion_wrong); /* Version Number, only supported value */
  996. }
  997. /* Frame Header Size */
  998. frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
  999. if (srcSize < frameHeaderSize) {
  1000. /* not enough input to fully decode frame header */
  1001. if (srcPtr != dctx->header)
  1002. memcpy(dctx->header, srcPtr, srcSize);
  1003. dctx->tmpInSize = srcSize;
  1004. dctx->tmpInTarget = frameHeaderSize;
  1005. dctx->dStage = dstage_storeFrameHeader;
  1006. return srcSize;
  1007. }
  1008. { U32 const BD = srcPtr[5];
  1009. blockSizeID = (BD>>4) & _3BITS;
  1010. /* validate */
  1011. if (((BD>>7)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */
  1012. if (blockSizeID < 4) return err0r(LZ4F_ERROR_maxBlockSize_invalid); /* 4-7 only supported values for the time being */
  1013. if (((BD>>0)&_4BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */
  1014. }
  1015. /* check header */
  1016. assert(frameHeaderSize > 5);
  1017. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1018. { BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);
  1019. if (HC != srcPtr[frameHeaderSize-1])
  1020. return err0r(LZ4F_ERROR_headerChecksum_invalid);
  1021. }
  1022. #endif
  1023. /* save */
  1024. dctx->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;
  1025. dctx->frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)blockChecksumFlag;
  1026. dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag;
  1027. dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID;
  1028. dctx->maxBlockSize = LZ4F_getBlockSize(blockSizeID);
  1029. if (contentSizeFlag)
  1030. dctx->frameRemainingSize =
  1031. dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6);
  1032. if (dictIDFlag)
  1033. dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5);
  1034. dctx->dStage = dstage_init;
  1035. return frameHeaderSize;
  1036. }
  1037. /*! LZ4F_headerSize() :
  1038. * @return : size of frame header
  1039. * or an error code, which can be tested using LZ4F_isError()
  1040. */
  1041. size_t LZ4F_headerSize(const void* src, size_t srcSize)
  1042. {
  1043. if (src == NULL) return err0r(LZ4F_ERROR_srcPtr_wrong);
  1044. /* minimal srcSize to determine header size */
  1045. if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH)
  1046. return err0r(LZ4F_ERROR_frameHeader_incomplete);
  1047. /* special case : skippable frames */
  1048. if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
  1049. return 8;
  1050. /* control magic number */
  1051. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1052. if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)
  1053. return err0r(LZ4F_ERROR_frameType_unknown);
  1054. #endif
  1055. /* Frame Header Size */
  1056. { BYTE const FLG = ((const BYTE*)src)[4];
  1057. U32 const contentSizeFlag = (FLG>>3) & _1BIT;
  1058. U32 const dictIDFlag = FLG & _1BIT;
  1059. return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);
  1060. }
  1061. }
  1062. /*! LZ4F_getFrameInfo() :
  1063. * This function extracts frame parameters (max blockSize, frame checksum, etc.).
  1064. * Usage is optional. Objective is to provide relevant information for allocation purposes.
  1065. * This function works in 2 situations :
  1066. * - At the beginning of a new frame, in which case it will decode this information from `srcBuffer`, and start the decoding process.
  1067. * Amount of input data provided must be large enough to successfully decode the frame header.
  1068. * 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.
  1069. * - After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx.
  1070. * The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
  1071. * Decompression must resume from (srcBuffer + *srcSizePtr).
  1072. * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
  1073. * or an error code which can be tested using LZ4F_isError()
  1074. * note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped.
  1075. * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.
  1076. */
  1077. LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
  1078. LZ4F_frameInfo_t* frameInfoPtr,
  1079. const void* srcBuffer, size_t* srcSizePtr)
  1080. {
  1081. LZ4F_STATIC_ASSERT(dstage_getFrameHeader < dstage_storeFrameHeader);
  1082. if (dctx->dStage > dstage_storeFrameHeader) {
  1083. /* frameInfo already decoded */
  1084. size_t o=0, i=0;
  1085. *srcSizePtr = 0;
  1086. *frameInfoPtr = dctx->frameInfo;
  1087. /* returns : recommended nb of bytes for LZ4F_decompress() */
  1088. return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL);
  1089. } else {
  1090. if (dctx->dStage == dstage_storeFrameHeader) {
  1091. /* frame decoding already started, in the middle of header => automatic fail */
  1092. *srcSizePtr = 0;
  1093. return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted);
  1094. } else {
  1095. size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);
  1096. if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }
  1097. if (*srcSizePtr < hSize) {
  1098. *srcSizePtr=0;
  1099. return err0r(LZ4F_ERROR_frameHeader_incomplete);
  1100. }
  1101. { size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);
  1102. if (LZ4F_isError(decodeResult)) {
  1103. *srcSizePtr = 0;
  1104. } else {
  1105. *srcSizePtr = decodeResult;
  1106. decodeResult = BHSize; /* block header size */
  1107. }
  1108. *frameInfoPtr = dctx->frameInfo;
  1109. return decodeResult;
  1110. } } }
  1111. }
  1112. /* LZ4F_updateDict() :
  1113. * only used for LZ4F_blockLinked mode */
  1114. static void LZ4F_updateDict(LZ4F_dctx* dctx,
  1115. const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,
  1116. unsigned withinTmp)
  1117. {
  1118. if (dctx->dictSize==0)
  1119. dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
  1120. if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity, directly within dstBuffer */
  1121. dctx->dictSize += dstSize;
  1122. return;
  1123. }
  1124. assert(dstPtr >= dstBufferStart);
  1125. if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */
  1126. dctx->dict = (const BYTE*)dstBufferStart;
  1127. dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize;
  1128. return;
  1129. }
  1130. assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */
  1131. /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOut */
  1132. if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
  1133. /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */
  1134. assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);
  1135. dctx->dictSize += dstSize;
  1136. return;
  1137. }
  1138. if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */
  1139. size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
  1140. size_t copySize = 64 KB - dctx->tmpOutSize;
  1141. const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
  1142. if (dctx->tmpOutSize > 64 KB) copySize = 0;
  1143. if (copySize > preserveSize) copySize = preserveSize;
  1144. memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
  1145. dctx->dict = dctx->tmpOutBuffer;
  1146. dctx->dictSize = preserveSize + dctx->tmpOutStart + dstSize;
  1147. return;
  1148. }
  1149. if (dctx->dict == dctx->tmpOutBuffer) { /* copy dst into tmp to complete dict */
  1150. if (dctx->dictSize + dstSize > dctx->maxBufferSize) { /* tmp buffer not large enough */
  1151. size_t const preserveSize = 64 KB - dstSize;
  1152. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
  1153. dctx->dictSize = preserveSize;
  1154. }
  1155. memcpy(dctx->tmpOutBuffer + dctx->dictSize, dstPtr, dstSize);
  1156. dctx->dictSize += dstSize;
  1157. return;
  1158. }
  1159. /* join dict & dest into tmp */
  1160. { size_t preserveSize = 64 KB - dstSize;
  1161. if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize;
  1162. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);
  1163. memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize);
  1164. dctx->dict = dctx->tmpOutBuffer;
  1165. dctx->dictSize = preserveSize + dstSize;
  1166. }
  1167. }
  1168. /*! LZ4F_decompress() :
  1169. * Call this function repetitively to regenerate compressed data in srcBuffer.
  1170. * The function will attempt to decode up to *srcSizePtr bytes from srcBuffer
  1171. * into dstBuffer of capacity *dstSizePtr.
  1172. *
  1173. * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
  1174. *
  1175. * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
  1176. * If number of bytes read is < number of bytes provided, then decompression operation is not complete.
  1177. * Remaining data will have to be presented again in a subsequent invocation.
  1178. *
  1179. * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.
  1180. * Schematically, it's the size of the current (or remaining) compressed block + header of next block.
  1181. * Respecting the hint provides a small boost to performance, since it allows less buffer shuffling.
  1182. * Note that this is just a hint, and it's always possible to any srcSize value.
  1183. * When a frame is fully decoded, @return will be 0.
  1184. * If decompression failed, @return is an error code which can be tested using LZ4F_isError().
  1185. */
  1186. size_t LZ4F_decompress(LZ4F_dctx* dctx,
  1187. void* dstBuffer, size_t* dstSizePtr,
  1188. const void* srcBuffer, size_t* srcSizePtr,
  1189. const LZ4F_decompressOptions_t* decompressOptionsPtr)
  1190. {
  1191. LZ4F_decompressOptions_t optionsNull;
  1192. const BYTE* const srcStart = (const BYTE*)srcBuffer;
  1193. const BYTE* const srcEnd = srcStart + *srcSizePtr;
  1194. const BYTE* srcPtr = srcStart;
  1195. BYTE* const dstStart = (BYTE*)dstBuffer;
  1196. BYTE* const dstEnd = dstStart + *dstSizePtr;
  1197. BYTE* dstPtr = dstStart;
  1198. const BYTE* selectedIn = NULL;
  1199. unsigned doAnotherStage = 1;
  1200. size_t nextSrcSizeHint = 1;
  1201. MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
  1202. if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
  1203. *srcSizePtr = 0;
  1204. *dstSizePtr = 0;
  1205. /* behaves as a state machine */
  1206. while (doAnotherStage) {
  1207. switch(dctx->dStage)
  1208. {
  1209. case dstage_getFrameHeader:
  1210. if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */
  1211. size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */
  1212. if (LZ4F_isError(hSize)) return hSize;
  1213. srcPtr += hSize;
  1214. break;
  1215. }
  1216. dctx->tmpInSize = 0;
  1217. if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */
  1218. dctx->tmpInTarget = minFHSize; /* minimum size to decode header */
  1219. dctx->dStage = dstage_storeFrameHeader;
  1220. /* fall-through */
  1221. case dstage_storeFrameHeader:
  1222. { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));
  1223. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1224. dctx->tmpInSize += sizeToCopy;
  1225. srcPtr += sizeToCopy;
  1226. }
  1227. if (dctx->tmpInSize < dctx->tmpInTarget) {
  1228. nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
  1229. doAnotherStage = 0; /* not enough src data, ask for some more */
  1230. break;
  1231. }
  1232. { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */
  1233. if (LZ4F_isError(hSize)) return hSize;
  1234. }
  1235. break;
  1236. case dstage_init:
  1237. if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);
  1238. /* internal buffers allocation */
  1239. { size_t const bufferNeeded = dctx->maxBlockSize
  1240. + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0);
  1241. if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */
  1242. dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/
  1243. FREEMEM(dctx->tmpIn);
  1244. dctx->tmpIn = (BYTE*)ALLOC(dctx->maxBlockSize + BFSize /* block checksum */);
  1245. if (dctx->tmpIn == NULL)
  1246. return err0r(LZ4F_ERROR_allocation_failed);
  1247. FREEMEM(dctx->tmpOutBuffer);
  1248. dctx->tmpOutBuffer= (BYTE*)ALLOC(bufferNeeded);
  1249. if (dctx->tmpOutBuffer== NULL)
  1250. return err0r(LZ4F_ERROR_allocation_failed);
  1251. dctx->maxBufferSize = bufferNeeded;
  1252. } }
  1253. dctx->tmpInSize = 0;
  1254. dctx->tmpInTarget = 0;
  1255. dctx->tmpOut = dctx->tmpOutBuffer;
  1256. dctx->tmpOutStart = 0;
  1257. dctx->tmpOutSize = 0;
  1258. dctx->dStage = dstage_getBlockHeader;
  1259. /* fall-through */
  1260. case dstage_getBlockHeader:
  1261. if ((size_t)(srcEnd - srcPtr) >= BHSize) {
  1262. selectedIn = srcPtr;
  1263. srcPtr += BHSize;
  1264. } else {
  1265. /* not enough input to read cBlockSize field */
  1266. dctx->tmpInSize = 0;
  1267. dctx->dStage = dstage_storeBlockHeader;
  1268. }
  1269. if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */
  1270. case dstage_storeBlockHeader:
  1271. { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
  1272. size_t const wantedData = BHSize - dctx->tmpInSize;
  1273. size_t const sizeToCopy = MIN(wantedData, remainingInput);
  1274. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1275. srcPtr += sizeToCopy;
  1276. dctx->tmpInSize += sizeToCopy;
  1277. if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */
  1278. nextSrcSizeHint = BHSize - dctx->tmpInSize;
  1279. doAnotherStage = 0;
  1280. break;
  1281. }
  1282. selectedIn = dctx->tmpIn;
  1283. } /* if (dctx->dStage == dstage_storeBlockHeader) */
  1284. /* decode block header */
  1285. { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU;
  1286. size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;
  1287. if (nextCBlockSize==0) { /* frameEnd signal, no more block */
  1288. dctx->dStage = dstage_getSuffix;
  1289. break;
  1290. }
  1291. if (nextCBlockSize > dctx->maxBlockSize)
  1292. return err0r(LZ4F_ERROR_maxBlockSize_invalid);
  1293. if (LZ4F_readLE32(selectedIn) & LZ4F_BLOCKUNCOMPRESSED_FLAG) {
  1294. /* next block is uncompressed */
  1295. dctx->tmpInTarget = nextCBlockSize;
  1296. if (dctx->frameInfo.blockChecksumFlag) {
  1297. (void)XXH32_reset(&dctx->blockChecksum, 0);
  1298. }
  1299. dctx->dStage = dstage_copyDirect;
  1300. break;
  1301. }
  1302. /* next block is a compressed block */
  1303. dctx->tmpInTarget = nextCBlockSize + crcSize;
  1304. dctx->dStage = dstage_getCBlock;
  1305. if (dstPtr==dstEnd || srcPtr==srcEnd) {
  1306. nextSrcSizeHint = BHSize + nextCBlockSize + crcSize;
  1307. doAnotherStage = 0;
  1308. }
  1309. break;
  1310. }
  1311. case dstage_copyDirect: /* uncompressed block */
  1312. { size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
  1313. size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
  1314. memcpy(dstPtr, srcPtr, sizeToCopy);
  1315. if (dctx->frameInfo.blockChecksumFlag) {
  1316. (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);
  1317. }
  1318. if (dctx->frameInfo.contentChecksumFlag)
  1319. (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);
  1320. if (dctx->frameInfo.contentSize)
  1321. dctx->frameRemainingSize -= sizeToCopy;
  1322. /* history management (linked blocks only)*/
  1323. if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
  1324. LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
  1325. srcPtr += sizeToCopy;
  1326. dstPtr += sizeToCopy;
  1327. if (sizeToCopy == dctx->tmpInTarget) { /* all done */
  1328. if (dctx->frameInfo.blockChecksumFlag) {
  1329. dctx->tmpInSize = 0;
  1330. dctx->dStage = dstage_getBlockChecksum;
  1331. } else
  1332. dctx->dStage = dstage_getBlockHeader; /* new block */
  1333. break;
  1334. }
  1335. dctx->tmpInTarget -= sizeToCopy; /* need to copy more */
  1336. nextSrcSizeHint = dctx->tmpInTarget +
  1337. +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
  1338. + BHSize /* next header size */;
  1339. doAnotherStage = 0;
  1340. break;
  1341. }
  1342. /* check block checksum for recently transferred uncompressed block */
  1343. case dstage_getBlockChecksum:
  1344. { const void* crcSrc;
  1345. if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {
  1346. crcSrc = srcPtr;
  1347. srcPtr += 4;
  1348. } else {
  1349. size_t const stillToCopy = 4 - dctx->tmpInSize;
  1350. size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr));
  1351. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1352. dctx->tmpInSize += sizeToCopy;
  1353. srcPtr += sizeToCopy;
  1354. if (dctx->tmpInSize < 4) { /* all input consumed */
  1355. doAnotherStage = 0;
  1356. break;
  1357. }
  1358. crcSrc = dctx->header;
  1359. }
  1360. { U32 const readCRC = LZ4F_readLE32(crcSrc);
  1361. U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);
  1362. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1363. if (readCRC != calcCRC)
  1364. return err0r(LZ4F_ERROR_blockChecksum_invalid);
  1365. #else
  1366. (void)readCRC;
  1367. (void)calcCRC;
  1368. #endif
  1369. } }
  1370. dctx->dStage = dstage_getBlockHeader; /* new block */
  1371. break;
  1372. case dstage_getCBlock:
  1373. if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {
  1374. dctx->tmpInSize = 0;
  1375. dctx->dStage = dstage_storeCBlock;
  1376. break;
  1377. }
  1378. /* input large enough to read full block directly */
  1379. selectedIn = srcPtr;
  1380. srcPtr += dctx->tmpInTarget;
  1381. if (0) /* jump over next block */
  1382. case dstage_storeCBlock:
  1383. { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
  1384. size_t const inputLeft = (size_t)(srcEnd-srcPtr);
  1385. size_t const sizeToCopy = MIN(wantedData, inputLeft);
  1386. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1387. dctx->tmpInSize += sizeToCopy;
  1388. srcPtr += sizeToCopy;
  1389. if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */
  1390. nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize)
  1391. + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0)
  1392. + BHSize /* next header size */;
  1393. doAnotherStage = 0;
  1394. break;
  1395. }
  1396. selectedIn = dctx->tmpIn;
  1397. }
  1398. /* At this stage, input is large enough to decode a block */
  1399. if (dctx->frameInfo.blockChecksumFlag) {
  1400. dctx->tmpInTarget -= 4;
  1401. assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */
  1402. { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);
  1403. U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);
  1404. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1405. if (readBlockCrc != calcBlockCrc)
  1406. return err0r(LZ4F_ERROR_blockChecksum_invalid);
  1407. #else
  1408. (void)readBlockCrc;
  1409. (void)calcBlockCrc;
  1410. #endif
  1411. } }
  1412. if ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize) {
  1413. const char* dict = (const char*)dctx->dict;
  1414. size_t dictSize = dctx->dictSize;
  1415. int decodedSize;
  1416. if (dict && dictSize > 1 GB) {
  1417. /* the dictSize param is an int, avoid truncation / sign issues */
  1418. dict += dictSize - 64 KB;
  1419. dictSize = 64 KB;
  1420. }
  1421. /* enough capacity in `dst` to decompress directly there */
  1422. decodedSize = LZ4_decompress_safe_usingDict(
  1423. (const char*)selectedIn, (char*)dstPtr,
  1424. (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
  1425. dict, (int)dictSize);
  1426. if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */
  1427. if (dctx->frameInfo.contentChecksumFlag)
  1428. XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize);
  1429. if (dctx->frameInfo.contentSize)
  1430. dctx->frameRemainingSize -= (size_t)decodedSize;
  1431. /* dictionary management */
  1432. if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
  1433. LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
  1434. dstPtr += decodedSize;
  1435. dctx->dStage = dstage_getBlockHeader;
  1436. break;
  1437. }
  1438. /* not enough place into dst : decode into tmpOut */
  1439. /* ensure enough place for tmpOut */
  1440. if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
  1441. if (dctx->dict == dctx->tmpOutBuffer) {
  1442. if (dctx->dictSize > 128 KB) {
  1443. memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB);
  1444. dctx->dictSize = 64 KB;
  1445. }
  1446. dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize;
  1447. } else { /* dict not within tmp */
  1448. size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);
  1449. dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;
  1450. } }
  1451. /* Decode block */
  1452. { const char* dict = (const char*)dctx->dict;
  1453. size_t dictSize = dctx->dictSize;
  1454. int decodedSize;
  1455. if (dict && dictSize > 1 GB) {
  1456. /* the dictSize param is an int, avoid truncation / sign issues */
  1457. dict += dictSize - 64 KB;
  1458. dictSize = 64 KB;
  1459. }
  1460. decodedSize = LZ4_decompress_safe_usingDict(
  1461. (const char*)selectedIn, (char*)dctx->tmpOut,
  1462. (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,
  1463. dict, (int)dictSize);
  1464. if (decodedSize < 0) /* decompression failed */
  1465. return err0r(LZ4F_ERROR_decompressionFailed);
  1466. if (dctx->frameInfo.contentChecksumFlag)
  1467. XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize);
  1468. if (dctx->frameInfo.contentSize)
  1469. dctx->frameRemainingSize -= (size_t)decodedSize;
  1470. dctx->tmpOutSize = (size_t)decodedSize;
  1471. dctx->tmpOutStart = 0;
  1472. dctx->dStage = dstage_flushOut;
  1473. }
  1474. /* fall-through */
  1475. case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
  1476. { size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
  1477. memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
  1478. /* dictionary management */
  1479. if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
  1480. LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/);
  1481. dctx->tmpOutStart += sizeToCopy;
  1482. dstPtr += sizeToCopy;
  1483. if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */
  1484. dctx->dStage = dstage_getBlockHeader; /* get next block */
  1485. break;
  1486. }
  1487. /* could not flush everything : stop there, just request a block header */
  1488. doAnotherStage = 0;
  1489. nextSrcSizeHint = BHSize;
  1490. break;
  1491. }
  1492. case dstage_getSuffix:
  1493. if (dctx->frameRemainingSize)
  1494. return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */
  1495. if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */
  1496. nextSrcSizeHint = 0;
  1497. LZ4F_resetDecompressionContext(dctx);
  1498. doAnotherStage = 0;
  1499. break;
  1500. }
  1501. if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */
  1502. dctx->tmpInSize = 0;
  1503. dctx->dStage = dstage_storeSuffix;
  1504. } else {
  1505. selectedIn = srcPtr;
  1506. srcPtr += 4;
  1507. }
  1508. if (dctx->dStage == dstage_storeSuffix) /* can be skipped */
  1509. case dstage_storeSuffix:
  1510. { size_t const remainingInput = (size_t)(srcEnd - srcPtr);
  1511. size_t const wantedData = 4 - dctx->tmpInSize;
  1512. size_t const sizeToCopy = MIN(wantedData, remainingInput);
  1513. memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);
  1514. srcPtr += sizeToCopy;
  1515. dctx->tmpInSize += sizeToCopy;
  1516. if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */
  1517. nextSrcSizeHint = 4 - dctx->tmpInSize;
  1518. doAnotherStage=0;
  1519. break;
  1520. }
  1521. selectedIn = dctx->tmpIn;
  1522. } /* if (dctx->dStage == dstage_storeSuffix) */
  1523. /* case dstage_checkSuffix: */ /* no direct entry, avoid initialization risks */
  1524. { U32 const readCRC = LZ4F_readLE32(selectedIn);
  1525. U32 const resultCRC = XXH32_digest(&(dctx->xxh));
  1526. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  1527. if (readCRC != resultCRC)
  1528. return err0r(LZ4F_ERROR_contentChecksum_invalid);
  1529. #else
  1530. (void)readCRC;
  1531. (void)resultCRC;
  1532. #endif
  1533. nextSrcSizeHint = 0;
  1534. LZ4F_resetDecompressionContext(dctx);
  1535. doAnotherStage = 0;
  1536. break;
  1537. }
  1538. case dstage_getSFrameSize:
  1539. if ((srcEnd - srcPtr) >= 4) {
  1540. selectedIn = srcPtr;
  1541. srcPtr += 4;
  1542. } else {
  1543. /* not enough input to read cBlockSize field */
  1544. dctx->tmpInSize = 4;
  1545. dctx->tmpInTarget = 8;
  1546. dctx->dStage = dstage_storeSFrameSize;
  1547. }
  1548. if (dctx->dStage == dstage_storeSFrameSize)
  1549. case dstage_storeSFrameSize:
  1550. { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,
  1551. (size_t)(srcEnd - srcPtr) );
  1552. memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);
  1553. srcPtr += sizeToCopy;
  1554. dctx->tmpInSize += sizeToCopy;
  1555. if (dctx->tmpInSize < dctx->tmpInTarget) {
  1556. /* not enough input to get full sBlockSize; wait for more */
  1557. nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize;
  1558. doAnotherStage = 0;
  1559. break;
  1560. }
  1561. selectedIn = dctx->header + 4;
  1562. } /* if (dctx->dStage == dstage_storeSFrameSize) */
  1563. /* case dstage_decodeSFrameSize: */ /* no direct entry */
  1564. { size_t const SFrameSize = LZ4F_readLE32(selectedIn);
  1565. dctx->frameInfo.contentSize = SFrameSize;
  1566. dctx->tmpInTarget = SFrameSize;
  1567. dctx->dStage = dstage_skipSkippable;
  1568. break;
  1569. }
  1570. case dstage_skipSkippable:
  1571. { size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr));
  1572. srcPtr += skipSize;
  1573. dctx->tmpInTarget -= skipSize;
  1574. doAnotherStage = 0;
  1575. nextSrcSizeHint = dctx->tmpInTarget;
  1576. if (nextSrcSizeHint) break; /* still more to skip */
  1577. /* frame fully skipped : prepare context for a new frame */
  1578. LZ4F_resetDecompressionContext(dctx);
  1579. break;
  1580. }
  1581. } /* switch (dctx->dStage) */
  1582. } /* while (doAnotherStage) */
  1583. /* preserve history within tmp whenever necessary */
  1584. LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);
  1585. if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */
  1586. && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */
  1587. && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */
  1588. && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */
  1589. {
  1590. if (dctx->dStage == dstage_flushOut) {
  1591. size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);
  1592. size_t copySize = 64 KB - dctx->tmpOutSize;
  1593. const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
  1594. if (dctx->tmpOutSize > 64 KB) copySize = 0;
  1595. if (copySize > preserveSize) copySize = preserveSize;
  1596. if (copySize > 0)
  1597. memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
  1598. dctx->dict = dctx->tmpOutBuffer;
  1599. dctx->dictSize = preserveSize + dctx->tmpOutStart;
  1600. } else {
  1601. const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
  1602. size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
  1603. if (newDictSize > 0)
  1604. memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
  1605. dctx->dict = dctx->tmpOutBuffer;
  1606. dctx->dictSize = newDictSize;
  1607. dctx->tmpOut = dctx->tmpOutBuffer + newDictSize;
  1608. }
  1609. }
  1610. *srcSizePtr = (size_t)(srcPtr - srcStart);
  1611. *dstSizePtr = (size_t)(dstPtr - dstStart);
  1612. return nextSrcSizeHint;
  1613. }
  1614. /*! LZ4F_decompress_usingDict() :
  1615. * Same as LZ4F_decompress(), using a predefined dictionary.
  1616. * Dictionary is used "in place", without any preprocessing.
  1617. * It must remain accessible throughout the entire frame decoding.
  1618. */
  1619. size_t LZ4F_decompress_usingDict(LZ4F_dctx* dctx,
  1620. void* dstBuffer, size_t* dstSizePtr,
  1621. const void* srcBuffer, size_t* srcSizePtr,
  1622. const void* dict, size_t dictSize,
  1623. const LZ4F_decompressOptions_t* decompressOptionsPtr)
  1624. {
  1625. if (dctx->dStage <= dstage_init) {
  1626. dctx->dict = (const BYTE*)dict;
  1627. dctx->dictSize = dictSize;
  1628. }
  1629. return LZ4F_decompress(dctx, dstBuffer, dstSizePtr,
  1630. srcBuffer, srcSizePtr,
  1631. decompressOptionsPtr);
  1632. }