zstd_compress_superblock.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. /*
  2. * Copyright (c) Yann Collet, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. * You may select, at your option, one of the above-listed licenses.
  9. */
  10. /*-*************************************
  11. * Dependencies
  12. ***************************************/
  13. #include "zstd_compress_superblock.h"
  14. #include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
  15. #include "hist.h" /* HIST_countFast_wksp */
  16. #include "zstd_compress_internal.h"
  17. #include "zstd_compress_sequences.h"
  18. #include "zstd_compress_literals.h"
  19. /*-*************************************
  20. * Superblock entropy buffer structs
  21. ***************************************/
  22. /* ZSTD_hufCTablesMetadata_t :
  23. * Stores Literals Block Type for a super-block in hType, and
  24. * huffman tree description in hufDesBuffer.
  25. * hufDesSize refers to the size of huffman tree description in bytes.
  26. * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
  27. typedef struct {
  28. symbolEncodingType_e hType;
  29. BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
  30. size_t hufDesSize;
  31. } ZSTD_hufCTablesMetadata_t;
  32. /* ZSTD_fseCTablesMetadata_t :
  33. * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
  34. * fse tables in fseTablesBuffer.
  35. * fseTablesSize refers to the size of fse tables in bytes.
  36. * This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */
  37. typedef struct {
  38. symbolEncodingType_e llType;
  39. symbolEncodingType_e ofType;
  40. symbolEncodingType_e mlType;
  41. BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
  42. size_t fseTablesSize;
  43. size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
  44. } ZSTD_fseCTablesMetadata_t;
  45. typedef struct {
  46. ZSTD_hufCTablesMetadata_t hufMetadata;
  47. ZSTD_fseCTablesMetadata_t fseMetadata;
  48. } ZSTD_entropyCTablesMetadata_t;
  49. /* ZSTD_buildSuperBlockEntropy_literal() :
  50. * Builds entropy for the super-block literals.
  51. * Stores literals block type (raw, rle, compressed, repeat) and
  52. * huffman description table to hufMetadata.
  53. * @return : size of huffman description table or error code */
  54. static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize,
  55. const ZSTD_hufCTables_t* prevHuf,
  56. ZSTD_hufCTables_t* nextHuf,
  57. ZSTD_hufCTablesMetadata_t* hufMetadata,
  58. const int disableLiteralsCompression,
  59. void* workspace, size_t wkspSize)
  60. {
  61. BYTE* const wkspStart = (BYTE*)workspace;
  62. BYTE* const wkspEnd = wkspStart + wkspSize;
  63. BYTE* const countWkspStart = wkspStart;
  64. unsigned* const countWksp = (unsigned*)workspace;
  65. const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
  66. BYTE* const nodeWksp = countWkspStart + countWkspSize;
  67. const size_t nodeWkspSize = wkspEnd-nodeWksp;
  68. unsigned maxSymbolValue = 255;
  69. unsigned huffLog = HUF_TABLELOG_DEFAULT;
  70. HUF_repeat repeat = prevHuf->repeatMode;
  71. DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
  72. /* Prepare nextEntropy assuming reusing the existing table */
  73. ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
  74. if (disableLiteralsCompression) {
  75. DEBUGLOG(5, "set_basic - disabled");
  76. hufMetadata->hType = set_basic;
  77. return 0;
  78. }
  79. /* small ? don't even attempt compression (speed opt) */
  80. # define COMPRESS_LITERALS_SIZE_MIN 63
  81. { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
  82. if (srcSize <= minLitSize) {
  83. DEBUGLOG(5, "set_basic - too small");
  84. hufMetadata->hType = set_basic;
  85. return 0;
  86. }
  87. }
  88. /* Scan input and build symbol stats */
  89. { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
  90. FORWARD_IF_ERROR(largest, "HIST_count_wksp failed");
  91. if (largest == srcSize) {
  92. DEBUGLOG(5, "set_rle");
  93. hufMetadata->hType = set_rle;
  94. return 0;
  95. }
  96. if (largest <= (srcSize >> 7)+4) {
  97. DEBUGLOG(5, "set_basic - no gain");
  98. hufMetadata->hType = set_basic;
  99. return 0;
  100. }
  101. }
  102. /* Validate the previous Huffman table */
  103. if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {
  104. repeat = HUF_repeat_none;
  105. }
  106. /* Build Huffman Tree */
  107. ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
  108. huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
  109. { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
  110. maxSymbolValue, huffLog,
  111. nodeWksp, nodeWkspSize);
  112. FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp");
  113. huffLog = (U32)maxBits;
  114. { /* Build and write the CTable */
  115. size_t const newCSize = HUF_estimateCompressedSize(
  116. (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
  117. size_t const hSize = HUF_writeCTable_wksp(
  118. hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
  119. (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,
  120. nodeWksp, nodeWkspSize);
  121. /* Check against repeating the previous CTable */
  122. if (repeat != HUF_repeat_none) {
  123. size_t const oldCSize = HUF_estimateCompressedSize(
  124. (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
  125. if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
  126. DEBUGLOG(5, "set_repeat - smaller");
  127. ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
  128. hufMetadata->hType = set_repeat;
  129. return 0;
  130. }
  131. }
  132. if (newCSize + hSize >= srcSize) {
  133. DEBUGLOG(5, "set_basic - no gains");
  134. ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
  135. hufMetadata->hType = set_basic;
  136. return 0;
  137. }
  138. DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
  139. hufMetadata->hType = set_compressed;
  140. nextHuf->repeatMode = HUF_repeat_check;
  141. return hSize;
  142. }
  143. }
  144. }
  145. /* ZSTD_buildSuperBlockEntropy_sequences() :
  146. * Builds entropy for the super-block sequences.
  147. * Stores symbol compression modes and fse table to fseMetadata.
  148. * @return : size of fse tables or error code */
  149. static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
  150. const ZSTD_fseCTables_t* prevEntropy,
  151. ZSTD_fseCTables_t* nextEntropy,
  152. const ZSTD_CCtx_params* cctxParams,
  153. ZSTD_fseCTablesMetadata_t* fseMetadata,
  154. void* workspace, size_t wkspSize)
  155. {
  156. BYTE* const wkspStart = (BYTE*)workspace;
  157. BYTE* const wkspEnd = wkspStart + wkspSize;
  158. BYTE* const countWkspStart = wkspStart;
  159. unsigned* const countWksp = (unsigned*)workspace;
  160. const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned);
  161. BYTE* const cTableWksp = countWkspStart + countWkspSize;
  162. const size_t cTableWkspSize = wkspEnd-cTableWksp;
  163. ZSTD_strategy const strategy = cctxParams->cParams.strategy;
  164. FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
  165. FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
  166. FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
  167. const BYTE* const ofCodeTable = seqStorePtr->ofCode;
  168. const BYTE* const llCodeTable = seqStorePtr->llCode;
  169. const BYTE* const mlCodeTable = seqStorePtr->mlCode;
  170. size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
  171. BYTE* const ostart = fseMetadata->fseTablesBuffer;
  172. BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
  173. BYTE* op = ostart;
  174. assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
  175. DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
  176. ZSTD_memset(workspace, 0, wkspSize);
  177. fseMetadata->lastCountSize = 0;
  178. /* convert length/distances into codes */
  179. ZSTD_seqToCodes(seqStorePtr);
  180. /* build CTable for Literal Lengths */
  181. { U32 LLtype;
  182. unsigned max = MaxLL;
  183. size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
  184. DEBUGLOG(5, "Building LL table");
  185. nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
  186. LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
  187. countWksp, max, mostFrequent, nbSeq,
  188. LLFSELog, prevEntropy->litlengthCTable,
  189. LL_defaultNorm, LL_defaultNormLog,
  190. ZSTD_defaultAllowed, strategy);
  191. assert(set_basic < set_compressed && set_rle < set_compressed);
  192. assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
  193. { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
  194. countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
  195. prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
  196. cTableWksp, cTableWkspSize);
  197. FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
  198. if (LLtype == set_compressed)
  199. fseMetadata->lastCountSize = countSize;
  200. op += countSize;
  201. fseMetadata->llType = (symbolEncodingType_e) LLtype;
  202. } }
  203. /* build CTable for Offsets */
  204. { U32 Offtype;
  205. unsigned max = MaxOff;
  206. size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
  207. /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
  208. ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
  209. DEBUGLOG(5, "Building OF table");
  210. nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
  211. Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
  212. countWksp, max, mostFrequent, nbSeq,
  213. OffFSELog, prevEntropy->offcodeCTable,
  214. OF_defaultNorm, OF_defaultNormLog,
  215. defaultPolicy, strategy);
  216. assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
  217. { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
  218. countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
  219. prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
  220. cTableWksp, cTableWkspSize);
  221. FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
  222. if (Offtype == set_compressed)
  223. fseMetadata->lastCountSize = countSize;
  224. op += countSize;
  225. fseMetadata->ofType = (symbolEncodingType_e) Offtype;
  226. } }
  227. /* build CTable for MatchLengths */
  228. { U32 MLtype;
  229. unsigned max = MaxML;
  230. size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
  231. DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
  232. nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
  233. MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
  234. countWksp, max, mostFrequent, nbSeq,
  235. MLFSELog, prevEntropy->matchlengthCTable,
  236. ML_defaultNorm, ML_defaultNormLog,
  237. ZSTD_defaultAllowed, strategy);
  238. assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
  239. { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
  240. countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
  241. prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
  242. cTableWksp, cTableWkspSize);
  243. FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
  244. if (MLtype == set_compressed)
  245. fseMetadata->lastCountSize = countSize;
  246. op += countSize;
  247. fseMetadata->mlType = (symbolEncodingType_e) MLtype;
  248. } }
  249. assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer));
  250. return op-ostart;
  251. }
  252. /* ZSTD_buildSuperBlockEntropy() :
  253. * Builds entropy for the super-block.
  254. * @return : 0 on success or error code */
  255. static size_t
  256. ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
  257. const ZSTD_entropyCTables_t* prevEntropy,
  258. ZSTD_entropyCTables_t* nextEntropy,
  259. const ZSTD_CCtx_params* cctxParams,
  260. ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  261. void* workspace, size_t wkspSize)
  262. {
  263. size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
  264. DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy");
  265. entropyMetadata->hufMetadata.hufDesSize =
  266. ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize,
  267. &prevEntropy->huf, &nextEntropy->huf,
  268. &entropyMetadata->hufMetadata,
  269. ZSTD_disableLiteralsCompression(cctxParams),
  270. workspace, wkspSize);
  271. FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed");
  272. entropyMetadata->fseMetadata.fseTablesSize =
  273. ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr,
  274. &prevEntropy->fse, &nextEntropy->fse,
  275. cctxParams,
  276. &entropyMetadata->fseMetadata,
  277. workspace, wkspSize);
  278. FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed");
  279. return 0;
  280. }
  281. /* ZSTD_compressSubBlock_literal() :
  282. * Compresses literals section for a sub-block.
  283. * When we have to write the Huffman table we will sometimes choose a header
  284. * size larger than necessary. This is because we have to pick the header size
  285. * before we know the table size + compressed size, so we have a bound on the
  286. * table size. If we guessed incorrectly, we fall back to uncompressed literals.
  287. *
  288. * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
  289. * in writing the header, otherwise it is set to 0.
  290. *
  291. * hufMetadata->hType has literals block type info.
  292. * If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block.
  293. * If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block.
  294. * If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block
  295. * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block
  296. * and the following sub-blocks' literals sections will be Treeless_Literals_Block.
  297. * @return : compressed size of literals section of a sub-block
  298. * Or 0 if it unable to compress.
  299. * Or error code */
  300. static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
  301. const ZSTD_hufCTablesMetadata_t* hufMetadata,
  302. const BYTE* literals, size_t litSize,
  303. void* dst, size_t dstSize,
  304. const int bmi2, int writeEntropy, int* entropyWritten)
  305. {
  306. size_t const header = writeEntropy ? 200 : 0;
  307. size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header));
  308. BYTE* const ostart = (BYTE*)dst;
  309. BYTE* const oend = ostart + dstSize;
  310. BYTE* op = ostart + lhSize;
  311. U32 const singleStream = lhSize == 3;
  312. symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;
  313. size_t cLitSize = 0;
  314. (void)bmi2; /* TODO bmi2... */
  315. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy);
  316. *entropyWritten = 0;
  317. if (litSize == 0 || hufMetadata->hType == set_basic) {
  318. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal");
  319. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  320. } else if (hufMetadata->hType == set_rle) {
  321. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using rle literal");
  322. return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize);
  323. }
  324. assert(litSize > 0);
  325. assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);
  326. if (writeEntropy && hufMetadata->hType == set_compressed) {
  327. ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
  328. op += hufMetadata->hufDesSize;
  329. cLitSize += hufMetadata->hufDesSize;
  330. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
  331. }
  332. /* TODO bmi2 */
  333. { const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable)
  334. : HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable);
  335. op += cSize;
  336. cLitSize += cSize;
  337. if (cSize == 0 || ERR_isError(cSize)) {
  338. DEBUGLOG(5, "Failed to write entropy tables %s", ZSTD_getErrorName(cSize));
  339. return 0;
  340. }
  341. /* If we expand and we aren't writing a header then emit uncompressed */
  342. if (!writeEntropy && cLitSize >= litSize) {
  343. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal because uncompressible");
  344. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  345. }
  346. /* If we are writing headers then allow expansion that doesn't change our header size. */
  347. if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) {
  348. assert(cLitSize > litSize);
  349. DEBUGLOG(5, "Literals expanded beyond allowed header size");
  350. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  351. }
  352. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize);
  353. }
  354. /* Build header */
  355. switch(lhSize)
  356. {
  357. case 3: /* 2 - 2 - 10 - 10 */
  358. { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
  359. MEM_writeLE24(ostart, lhc);
  360. break;
  361. }
  362. case 4: /* 2 - 2 - 14 - 14 */
  363. { U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18);
  364. MEM_writeLE32(ostart, lhc);
  365. break;
  366. }
  367. case 5: /* 2 - 2 - 18 - 18 */
  368. { U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22);
  369. MEM_writeLE32(ostart, lhc);
  370. ostart[4] = (BYTE)(cLitSize >> 10);
  371. break;
  372. }
  373. default: /* not possible : lhSize is {3,4,5} */
  374. assert(0);
  375. }
  376. *entropyWritten = 1;
  377. DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart));
  378. return op-ostart;
  379. }
  380. static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef* sequences, size_t nbSeq, size_t litSize, int lastSequence) {
  381. const seqDef* const sstart = sequences;
  382. const seqDef* const send = sequences + nbSeq;
  383. const seqDef* sp = sstart;
  384. size_t matchLengthSum = 0;
  385. size_t litLengthSum = 0;
  386. /* Only used by assert(), suppress unused variable warnings in production. */
  387. (void)litLengthSum;
  388. while (send-sp > 0) {
  389. ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
  390. litLengthSum += seqLen.litLength;
  391. matchLengthSum += seqLen.matchLength;
  392. sp++;
  393. }
  394. assert(litLengthSum <= litSize);
  395. if (!lastSequence) {
  396. assert(litLengthSum == litSize);
  397. }
  398. return matchLengthSum + litSize;
  399. }
  400. /* ZSTD_compressSubBlock_sequences() :
  401. * Compresses sequences section for a sub-block.
  402. * fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have
  403. * symbol compression modes for the super-block.
  404. * The first successfully compressed block will have these in its header.
  405. * We set entropyWritten=1 when we succeed in compressing the sequences.
  406. * The following sub-blocks will always have repeat mode.
  407. * @return : compressed size of sequences section of a sub-block
  408. * Or 0 if it is unable to compress
  409. * Or error code. */
  410. static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
  411. const ZSTD_fseCTablesMetadata_t* fseMetadata,
  412. const seqDef* sequences, size_t nbSeq,
  413. const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
  414. const ZSTD_CCtx_params* cctxParams,
  415. void* dst, size_t dstCapacity,
  416. const int bmi2, int writeEntropy, int* entropyWritten)
  417. {
  418. const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
  419. BYTE* const ostart = (BYTE*)dst;
  420. BYTE* const oend = ostart + dstCapacity;
  421. BYTE* op = ostart;
  422. BYTE* seqHead;
  423. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets);
  424. *entropyWritten = 0;
  425. /* Sequences Header */
  426. RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
  427. dstSize_tooSmall, "");
  428. if (nbSeq < 0x7F)
  429. *op++ = (BYTE)nbSeq;
  430. else if (nbSeq < LONGNBSEQ)
  431. op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
  432. else
  433. op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
  434. if (nbSeq==0) {
  435. return op - ostart;
  436. }
  437. /* seqHead : flags for FSE encoding type */
  438. seqHead = op++;
  439. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (seqHeadSize=%u)", (unsigned)(op-ostart));
  440. if (writeEntropy) {
  441. const U32 LLtype = fseMetadata->llType;
  442. const U32 Offtype = fseMetadata->ofType;
  443. const U32 MLtype = fseMetadata->mlType;
  444. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
  445. *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
  446. ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
  447. op += fseMetadata->fseTablesSize;
  448. } else {
  449. const U32 repeat = set_repeat;
  450. *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2));
  451. }
  452. { size_t const bitstreamSize = ZSTD_encodeSequences(
  453. op, oend - op,
  454. fseTables->matchlengthCTable, mlCode,
  455. fseTables->offcodeCTable, ofCode,
  456. fseTables->litlengthCTable, llCode,
  457. sequences, nbSeq,
  458. longOffsets, bmi2);
  459. FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
  460. op += bitstreamSize;
  461. /* zstd versions <= 1.3.4 mistakenly report corruption when
  462. * FSE_readNCount() receives a buffer < 4 bytes.
  463. * Fixed by https://github.com/facebook/zstd/pull/1146.
  464. * This can happen when the last set_compressed table present is 2
  465. * bytes and the bitstream is only one byte.
  466. * In this exceedingly rare case, we will simply emit an uncompressed
  467. * block, since it isn't worth optimizing.
  468. */
  469. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  470. if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {
  471. /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
  472. assert(fseMetadata->lastCountSize + bitstreamSize == 3);
  473. DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
  474. "emitting an uncompressed block.");
  475. return 0;
  476. }
  477. #endif
  478. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize);
  479. }
  480. /* zstd versions <= 1.4.0 mistakenly report error when
  481. * sequences section body size is less than 3 bytes.
  482. * Fixed by https://github.com/facebook/zstd/pull/1664.
  483. * This can happen when the previous sequences section block is compressed
  484. * with rle mode and the current block's sequences section is compressed
  485. * with repeat mode where sequences section body size can be 1 byte.
  486. */
  487. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  488. if (op-seqHead < 4) {
  489. DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting "
  490. "an uncompressed block when sequences are < 4 bytes");
  491. return 0;
  492. }
  493. #endif
  494. *entropyWritten = 1;
  495. return op - ostart;
  496. }
  497. /* ZSTD_compressSubBlock() :
  498. * Compresses a single sub-block.
  499. * @return : compressed size of the sub-block
  500. * Or 0 if it failed to compress. */
  501. static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
  502. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  503. const seqDef* sequences, size_t nbSeq,
  504. const BYTE* literals, size_t litSize,
  505. const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
  506. const ZSTD_CCtx_params* cctxParams,
  507. void* dst, size_t dstCapacity,
  508. const int bmi2,
  509. int writeLitEntropy, int writeSeqEntropy,
  510. int* litEntropyWritten, int* seqEntropyWritten,
  511. U32 lastBlock)
  512. {
  513. BYTE* const ostart = (BYTE*)dst;
  514. BYTE* const oend = ostart + dstCapacity;
  515. BYTE* op = ostart + ZSTD_blockHeaderSize;
  516. DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)",
  517. litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);
  518. { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,
  519. &entropyMetadata->hufMetadata, literals, litSize,
  520. op, oend-op, bmi2, writeLitEntropy, litEntropyWritten);
  521. FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed");
  522. if (cLitSize == 0) return 0;
  523. op += cLitSize;
  524. }
  525. { size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse,
  526. &entropyMetadata->fseMetadata,
  527. sequences, nbSeq,
  528. llCode, mlCode, ofCode,
  529. cctxParams,
  530. op, oend-op,
  531. bmi2, writeSeqEntropy, seqEntropyWritten);
  532. FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed");
  533. if (cSeqSize == 0) return 0;
  534. op += cSeqSize;
  535. }
  536. /* Write block header */
  537. { size_t cSize = (op-ostart)-ZSTD_blockHeaderSize;
  538. U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
  539. MEM_writeLE24(ostart, cBlockHeader24);
  540. }
  541. return op-ostart;
  542. }
  543. static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,
  544. const ZSTD_hufCTables_t* huf,
  545. const ZSTD_hufCTablesMetadata_t* hufMetadata,
  546. void* workspace, size_t wkspSize,
  547. int writeEntropy)
  548. {
  549. unsigned* const countWksp = (unsigned*)workspace;
  550. unsigned maxSymbolValue = 255;
  551. size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
  552. if (hufMetadata->hType == set_basic) return litSize;
  553. else if (hufMetadata->hType == set_rle) return 1;
  554. else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {
  555. size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);
  556. if (ZSTD_isError(largest)) return litSize;
  557. { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);
  558. if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;
  559. return cLitSizeEstimate + literalSectionHeaderSize;
  560. } }
  561. assert(0); /* impossible */
  562. return 0;
  563. }
  564. static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
  565. const BYTE* codeTable, unsigned maxCode,
  566. size_t nbSeq, const FSE_CTable* fseCTable,
  567. const U32* additionalBits,
  568. short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
  569. void* workspace, size_t wkspSize)
  570. {
  571. unsigned* const countWksp = (unsigned*)workspace;
  572. const BYTE* ctp = codeTable;
  573. const BYTE* const ctStart = ctp;
  574. const BYTE* const ctEnd = ctStart + nbSeq;
  575. size_t cSymbolTypeSizeEstimateInBits = 0;
  576. unsigned max = maxCode;
  577. HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
  578. if (type == set_basic) {
  579. /* We selected this encoding type, so it must be valid. */
  580. assert(max <= defaultMax);
  581. cSymbolTypeSizeEstimateInBits = max <= defaultMax
  582. ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
  583. : ERROR(GENERIC);
  584. } else if (type == set_rle) {
  585. cSymbolTypeSizeEstimateInBits = 0;
  586. } else if (type == set_compressed || type == set_repeat) {
  587. cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);
  588. }
  589. if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10;
  590. while (ctp < ctEnd) {
  591. if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];
  592. else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */
  593. ctp++;
  594. }
  595. return cSymbolTypeSizeEstimateInBits / 8;
  596. }
  597. static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
  598. const BYTE* llCodeTable,
  599. const BYTE* mlCodeTable,
  600. size_t nbSeq,
  601. const ZSTD_fseCTables_t* fseTables,
  602. const ZSTD_fseCTablesMetadata_t* fseMetadata,
  603. void* workspace, size_t wkspSize,
  604. int writeEntropy)
  605. {
  606. size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
  607. size_t cSeqSizeEstimate = 0;
  608. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
  609. nbSeq, fseTables->offcodeCTable, NULL,
  610. OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
  611. workspace, wkspSize);
  612. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
  613. nbSeq, fseTables->litlengthCTable, LL_bits,
  614. LL_defaultNorm, LL_defaultNormLog, MaxLL,
  615. workspace, wkspSize);
  616. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
  617. nbSeq, fseTables->matchlengthCTable, ML_bits,
  618. ML_defaultNorm, ML_defaultNormLog, MaxML,
  619. workspace, wkspSize);
  620. if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
  621. return cSeqSizeEstimate + sequencesSectionHeaderSize;
  622. }
  623. static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
  624. const BYTE* ofCodeTable,
  625. const BYTE* llCodeTable,
  626. const BYTE* mlCodeTable,
  627. size_t nbSeq,
  628. const ZSTD_entropyCTables_t* entropy,
  629. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  630. void* workspace, size_t wkspSize,
  631. int writeLitEntropy, int writeSeqEntropy) {
  632. size_t cSizeEstimate = 0;
  633. cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize,
  634. &entropy->huf, &entropyMetadata->hufMetadata,
  635. workspace, wkspSize, writeLitEntropy);
  636. cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
  637. nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
  638. workspace, wkspSize, writeSeqEntropy);
  639. return cSizeEstimate + ZSTD_blockHeaderSize;
  640. }
  641. static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)
  642. {
  643. if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle)
  644. return 1;
  645. if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle)
  646. return 1;
  647. if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle)
  648. return 1;
  649. return 0;
  650. }
  651. /* ZSTD_compressSubBlock_multi() :
  652. * Breaks super-block into multiple sub-blocks and compresses them.
  653. * Entropy will be written to the first block.
  654. * The following blocks will use repeat mode to compress.
  655. * All sub-blocks are compressed blocks (no raw or rle blocks).
  656. * @return : compressed size of the super block (which is multiple ZSTD blocks)
  657. * Or 0 if it failed to compress. */
  658. static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
  659. const ZSTD_compressedBlockState_t* prevCBlock,
  660. ZSTD_compressedBlockState_t* nextCBlock,
  661. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  662. const ZSTD_CCtx_params* cctxParams,
  663. void* dst, size_t dstCapacity,
  664. const void* src, size_t srcSize,
  665. const int bmi2, U32 lastBlock,
  666. void* workspace, size_t wkspSize)
  667. {
  668. const seqDef* const sstart = seqStorePtr->sequencesStart;
  669. const seqDef* const send = seqStorePtr->sequences;
  670. const seqDef* sp = sstart;
  671. const BYTE* const lstart = seqStorePtr->litStart;
  672. const BYTE* const lend = seqStorePtr->lit;
  673. const BYTE* lp = lstart;
  674. BYTE const* ip = (BYTE const*)src;
  675. BYTE const* const iend = ip + srcSize;
  676. BYTE* const ostart = (BYTE*)dst;
  677. BYTE* const oend = ostart + dstCapacity;
  678. BYTE* op = ostart;
  679. const BYTE* llCodePtr = seqStorePtr->llCode;
  680. const BYTE* mlCodePtr = seqStorePtr->mlCode;
  681. const BYTE* ofCodePtr = seqStorePtr->ofCode;
  682. size_t targetCBlockSize = cctxParams->targetCBlockSize;
  683. size_t litSize, seqCount;
  684. int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed;
  685. int writeSeqEntropy = 1;
  686. int lastSequence = 0;
  687. DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)",
  688. (unsigned)(lend-lp), (unsigned)(send-sstart));
  689. litSize = 0;
  690. seqCount = 0;
  691. do {
  692. size_t cBlockSizeEstimate = 0;
  693. if (sstart == send) {
  694. lastSequence = 1;
  695. } else {
  696. const seqDef* const sequence = sp + seqCount;
  697. lastSequence = sequence == send - 1;
  698. litSize += ZSTD_getSequenceLength(seqStorePtr, sequence).litLength;
  699. seqCount++;
  700. }
  701. if (lastSequence) {
  702. assert(lp <= lend);
  703. assert(litSize <= (size_t)(lend - lp));
  704. litSize = (size_t)(lend - lp);
  705. }
  706. /* I think there is an optimization opportunity here.
  707. * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful
  708. * since it recalculates estimate from scratch.
  709. * For example, it would recount literal distribution and symbol codes everytime.
  710. */
  711. cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
  712. &nextCBlock->entropy, entropyMetadata,
  713. workspace, wkspSize, writeLitEntropy, writeSeqEntropy);
  714. if (cBlockSizeEstimate > targetCBlockSize || lastSequence) {
  715. int litEntropyWritten = 0;
  716. int seqEntropyWritten = 0;
  717. const size_t decompressedSize = ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSequence);
  718. const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
  719. sp, seqCount,
  720. lp, litSize,
  721. llCodePtr, mlCodePtr, ofCodePtr,
  722. cctxParams,
  723. op, oend-op,
  724. bmi2, writeLitEntropy, writeSeqEntropy,
  725. &litEntropyWritten, &seqEntropyWritten,
  726. lastBlock && lastSequence);
  727. FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
  728. if (cSize > 0 && cSize < decompressedSize) {
  729. DEBUGLOG(5, "Committed the sub-block");
  730. assert(ip + decompressedSize <= iend);
  731. ip += decompressedSize;
  732. sp += seqCount;
  733. lp += litSize;
  734. op += cSize;
  735. llCodePtr += seqCount;
  736. mlCodePtr += seqCount;
  737. ofCodePtr += seqCount;
  738. litSize = 0;
  739. seqCount = 0;
  740. /* Entropy only needs to be written once */
  741. if (litEntropyWritten) {
  742. writeLitEntropy = 0;
  743. }
  744. if (seqEntropyWritten) {
  745. writeSeqEntropy = 0;
  746. }
  747. }
  748. }
  749. } while (!lastSequence);
  750. if (writeLitEntropy) {
  751. DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
  752. ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
  753. }
  754. if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
  755. /* If we haven't written our entropy tables, then we've violated our contract and
  756. * must emit an uncompressed block.
  757. */
  758. DEBUGLOG(5, "ZSTD_compressSubBlock_multi has sequence entropy tables unwritten");
  759. return 0;
  760. }
  761. if (ip < iend) {
  762. size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock);
  763. DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip));
  764. FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
  765. assert(cSize != 0);
  766. op += cSize;
  767. /* We have to regenerate the repcodes because we've skipped some sequences */
  768. if (sp < send) {
  769. seqDef const* seq;
  770. repcodes_t rep;
  771. ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
  772. for (seq = sstart; seq < sp; ++seq) {
  773. rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
  774. }
  775. ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
  776. }
  777. }
  778. DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
  779. return op-ostart;
  780. }
  781. size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
  782. void* dst, size_t dstCapacity,
  783. void const* src, size_t srcSize,
  784. unsigned lastBlock) {
  785. ZSTD_entropyCTablesMetadata_t entropyMetadata;
  786. FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore,
  787. &zc->blockState.prevCBlock->entropy,
  788. &zc->blockState.nextCBlock->entropy,
  789. &zc->appliedParams,
  790. &entropyMetadata,
  791. zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
  792. return ZSTD_compressSubBlock_multi(&zc->seqStore,
  793. zc->blockState.prevCBlock,
  794. zc->blockState.nextCBlock,
  795. &entropyMetadata,
  796. &zc->appliedParams,
  797. dst, dstCapacity,
  798. src, srcSize,
  799. zc->bmi2, lastBlock,
  800. zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
  801. }