zstd_compress_superblock.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  2. /*
  3. * Copyright (c) Meta Platforms, Inc. and affiliates.
  4. * All rights reserved.
  5. *
  6. * This source code is licensed under both the BSD-style license (found in the
  7. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  8. * in the COPYING file in the root directory of this source tree).
  9. * You may select, at your option, one of the above-listed licenses.
  10. */
  11. /*-*************************************
  12. * Dependencies
  13. ***************************************/
  14. #include "zstd_compress_superblock.h"
  15. #include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
  16. #include "hist.h" /* HIST_countFast_wksp */
  17. #include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */
  18. #include "zstd_compress_sequences.h"
  19. #include "zstd_compress_literals.h"
  20. /* ZSTD_compressSubBlock_literal() :
  21. * Compresses literals section for a sub-block.
  22. * When we have to write the Huffman table we will sometimes choose a header
  23. * size larger than necessary. This is because we have to pick the header size
  24. * before we know the table size + compressed size, so we have a bound on the
  25. * table size. If we guessed incorrectly, we fall back to uncompressed literals.
  26. *
  27. * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
  28. * in writing the header, otherwise it is set to 0.
  29. *
  30. * hufMetadata->hType has literals block type info.
  31. * If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block.
  32. * If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block.
  33. * If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block
  34. * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block
  35. * and the following sub-blocks' literals sections will be Treeless_Literals_Block.
  36. * @return : compressed size of literals section of a sub-block
  37. * Or 0 if unable to compress.
  38. * Or error code */
  39. static size_t
  40. ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
  41. const ZSTD_hufCTablesMetadata_t* hufMetadata,
  42. const BYTE* literals, size_t litSize,
  43. void* dst, size_t dstSize,
  44. const int bmi2, int writeEntropy, int* entropyWritten)
  45. {
  46. size_t const header = writeEntropy ? 200 : 0;
  47. size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header));
  48. BYTE* const ostart = (BYTE*)dst;
  49. BYTE* const oend = ostart + dstSize;
  50. BYTE* op = ostart + lhSize;
  51. U32 const singleStream = lhSize == 3;
  52. SymbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;
  53. size_t cLitSize = 0;
  54. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy);
  55. *entropyWritten = 0;
  56. if (litSize == 0 || hufMetadata->hType == set_basic) {
  57. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal");
  58. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  59. } else if (hufMetadata->hType == set_rle) {
  60. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using rle literal");
  61. return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize);
  62. }
  63. assert(litSize > 0);
  64. assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);
  65. if (writeEntropy && hufMetadata->hType == set_compressed) {
  66. ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
  67. op += hufMetadata->hufDesSize;
  68. cLitSize += hufMetadata->hufDesSize;
  69. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
  70. }
  71. { int const flags = bmi2 ? HUF_flags_bmi2 : 0;
  72. const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags)
  73. : HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags);
  74. op += cSize;
  75. cLitSize += cSize;
  76. if (cSize == 0 || ERR_isError(cSize)) {
  77. DEBUGLOG(5, "Failed to write entropy tables %s", ZSTD_getErrorName(cSize));
  78. return 0;
  79. }
  80. /* If we expand and we aren't writing a header then emit uncompressed */
  81. if (!writeEntropy && cLitSize >= litSize) {
  82. DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal because uncompressible");
  83. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  84. }
  85. /* If we are writing headers then allow expansion that doesn't change our header size. */
  86. if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) {
  87. assert(cLitSize > litSize);
  88. DEBUGLOG(5, "Literals expanded beyond allowed header size");
  89. return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
  90. }
  91. DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize);
  92. }
  93. /* Build header */
  94. switch(lhSize)
  95. {
  96. case 3: /* 2 - 2 - 10 - 10 */
  97. { U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
  98. MEM_writeLE24(ostart, lhc);
  99. break;
  100. }
  101. case 4: /* 2 - 2 - 14 - 14 */
  102. { U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18);
  103. MEM_writeLE32(ostart, lhc);
  104. break;
  105. }
  106. case 5: /* 2 - 2 - 18 - 18 */
  107. { U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22);
  108. MEM_writeLE32(ostart, lhc);
  109. ostart[4] = (BYTE)(cLitSize >> 10);
  110. break;
  111. }
  112. default: /* not possible : lhSize is {3,4,5} */
  113. assert(0);
  114. }
  115. *entropyWritten = 1;
  116. DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart));
  117. return (size_t)(op-ostart);
  118. }
  119. static size_t
  120. ZSTD_seqDecompressedSize(SeqStore_t const* seqStore,
  121. const SeqDef* sequences, size_t nbSeqs,
  122. size_t litSize, int lastSubBlock)
  123. {
  124. size_t matchLengthSum = 0;
  125. size_t litLengthSum = 0;
  126. size_t n;
  127. for (n=0; n<nbSeqs; n++) {
  128. const ZSTD_SequenceLength seqLen = ZSTD_getSequenceLength(seqStore, sequences+n);
  129. litLengthSum += seqLen.litLength;
  130. matchLengthSum += seqLen.matchLength;
  131. }
  132. DEBUGLOG(5, "ZSTD_seqDecompressedSize: %u sequences from %p: %u literals + %u matchlength",
  133. (unsigned)nbSeqs, (const void*)sequences,
  134. (unsigned)litLengthSum, (unsigned)matchLengthSum);
  135. if (!lastSubBlock)
  136. assert(litLengthSum == litSize);
  137. else
  138. assert(litLengthSum <= litSize);
  139. (void)litLengthSum;
  140. return matchLengthSum + litSize;
  141. }
  142. /* ZSTD_compressSubBlock_sequences() :
  143. * Compresses sequences section for a sub-block.
  144. * fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have
  145. * symbol compression modes for the super-block.
  146. * The first successfully compressed block will have these in its header.
  147. * We set entropyWritten=1 when we succeed in compressing the sequences.
  148. * The following sub-blocks will always have repeat mode.
  149. * @return : compressed size of sequences section of a sub-block
  150. * Or 0 if it is unable to compress
  151. * Or error code. */
  152. static size_t
  153. ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
  154. const ZSTD_fseCTablesMetadata_t* fseMetadata,
  155. const SeqDef* sequences, size_t nbSeq,
  156. const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
  157. const ZSTD_CCtx_params* cctxParams,
  158. void* dst, size_t dstCapacity,
  159. const int bmi2, int writeEntropy, int* entropyWritten)
  160. {
  161. const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
  162. BYTE* const ostart = (BYTE*)dst;
  163. BYTE* const oend = ostart + dstCapacity;
  164. BYTE* op = ostart;
  165. BYTE* seqHead;
  166. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets);
  167. *entropyWritten = 0;
  168. /* Sequences Header */
  169. RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
  170. dstSize_tooSmall, "");
  171. if (nbSeq < 128)
  172. *op++ = (BYTE)nbSeq;
  173. else if (nbSeq < LONGNBSEQ)
  174. op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
  175. else
  176. op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
  177. if (nbSeq==0) {
  178. return (size_t)(op - ostart);
  179. }
  180. /* seqHead : flags for FSE encoding type */
  181. seqHead = op++;
  182. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (seqHeadSize=%u)", (unsigned)(op-ostart));
  183. if (writeEntropy) {
  184. const U32 LLtype = fseMetadata->llType;
  185. const U32 Offtype = fseMetadata->ofType;
  186. const U32 MLtype = fseMetadata->mlType;
  187. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
  188. *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
  189. ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
  190. op += fseMetadata->fseTablesSize;
  191. } else {
  192. const U32 repeat = set_repeat;
  193. *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2));
  194. }
  195. { size_t const bitstreamSize = ZSTD_encodeSequences(
  196. op, (size_t)(oend - op),
  197. fseTables->matchlengthCTable, mlCode,
  198. fseTables->offcodeCTable, ofCode,
  199. fseTables->litlengthCTable, llCode,
  200. sequences, nbSeq,
  201. longOffsets, bmi2);
  202. FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
  203. op += bitstreamSize;
  204. /* zstd versions <= 1.3.4 mistakenly report corruption when
  205. * FSE_readNCount() receives a buffer < 4 bytes.
  206. * Fixed by https://github.com/facebook/zstd/pull/1146.
  207. * This can happen when the last set_compressed table present is 2
  208. * bytes and the bitstream is only one byte.
  209. * In this exceedingly rare case, we will simply emit an uncompressed
  210. * block, since it isn't worth optimizing.
  211. */
  212. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  213. if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {
  214. /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
  215. assert(fseMetadata->lastCountSize + bitstreamSize == 3);
  216. DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
  217. "emitting an uncompressed block.");
  218. return 0;
  219. }
  220. #endif
  221. DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize);
  222. }
  223. /* zstd versions <= 1.4.0 mistakenly report error when
  224. * sequences section body size is less than 3 bytes.
  225. * Fixed by https://github.com/facebook/zstd/pull/1664.
  226. * This can happen when the previous sequences section block is compressed
  227. * with rle mode and the current block's sequences section is compressed
  228. * with repeat mode where sequences section body size can be 1 byte.
  229. */
  230. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  231. if (op-seqHead < 4) {
  232. DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting "
  233. "an uncompressed block when sequences are < 4 bytes");
  234. return 0;
  235. }
  236. #endif
  237. *entropyWritten = 1;
  238. return (size_t)(op - ostart);
  239. }
  240. /* ZSTD_compressSubBlock() :
  241. * Compresses a single sub-block.
  242. * @return : compressed size of the sub-block
  243. * Or 0 if it failed to compress. */
  244. static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
  245. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  246. const SeqDef* sequences, size_t nbSeq,
  247. const BYTE* literals, size_t litSize,
  248. const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
  249. const ZSTD_CCtx_params* cctxParams,
  250. void* dst, size_t dstCapacity,
  251. const int bmi2,
  252. int writeLitEntropy, int writeSeqEntropy,
  253. int* litEntropyWritten, int* seqEntropyWritten,
  254. U32 lastBlock)
  255. {
  256. BYTE* const ostart = (BYTE*)dst;
  257. BYTE* const oend = ostart + dstCapacity;
  258. BYTE* op = ostart + ZSTD_blockHeaderSize;
  259. DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)",
  260. litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);
  261. { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,
  262. &entropyMetadata->hufMetadata, literals, litSize,
  263. op, (size_t)(oend-op),
  264. bmi2, writeLitEntropy, litEntropyWritten);
  265. FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed");
  266. if (cLitSize == 0) return 0;
  267. op += cLitSize;
  268. }
  269. { size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse,
  270. &entropyMetadata->fseMetadata,
  271. sequences, nbSeq,
  272. llCode, mlCode, ofCode,
  273. cctxParams,
  274. op, (size_t)(oend-op),
  275. bmi2, writeSeqEntropy, seqEntropyWritten);
  276. FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed");
  277. if (cSeqSize == 0) return 0;
  278. op += cSeqSize;
  279. }
  280. /* Write block header */
  281. { size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize;
  282. U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
  283. MEM_writeLE24(ostart, cBlockHeader24);
  284. }
  285. return (size_t)(op-ostart);
  286. }
  287. static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,
  288. const ZSTD_hufCTables_t* huf,
  289. const ZSTD_hufCTablesMetadata_t* hufMetadata,
  290. void* workspace, size_t wkspSize,
  291. int writeEntropy)
  292. {
  293. unsigned* const countWksp = (unsigned*)workspace;
  294. unsigned maxSymbolValue = 255;
  295. size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
  296. if (hufMetadata->hType == set_basic) return litSize;
  297. else if (hufMetadata->hType == set_rle) return 1;
  298. else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {
  299. size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);
  300. if (ZSTD_isError(largest)) return litSize;
  301. { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);
  302. if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;
  303. return cLitSizeEstimate + literalSectionHeaderSize;
  304. } }
  305. assert(0); /* impossible */
  306. return 0;
  307. }
  308. static size_t ZSTD_estimateSubBlockSize_symbolType(SymbolEncodingType_e type,
  309. const BYTE* codeTable, unsigned maxCode,
  310. size_t nbSeq, const FSE_CTable* fseCTable,
  311. const U8* additionalBits,
  312. short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
  313. void* workspace, size_t wkspSize)
  314. {
  315. unsigned* const countWksp = (unsigned*)workspace;
  316. const BYTE* ctp = codeTable;
  317. const BYTE* const ctStart = ctp;
  318. const BYTE* const ctEnd = ctStart + nbSeq;
  319. size_t cSymbolTypeSizeEstimateInBits = 0;
  320. unsigned max = maxCode;
  321. HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
  322. if (type == set_basic) {
  323. /* We selected this encoding type, so it must be valid. */
  324. assert(max <= defaultMax);
  325. cSymbolTypeSizeEstimateInBits = max <= defaultMax
  326. ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
  327. : ERROR(GENERIC);
  328. } else if (type == set_rle) {
  329. cSymbolTypeSizeEstimateInBits = 0;
  330. } else if (type == set_compressed || type == set_repeat) {
  331. cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);
  332. }
  333. if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10;
  334. while (ctp < ctEnd) {
  335. if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];
  336. else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */
  337. ctp++;
  338. }
  339. return cSymbolTypeSizeEstimateInBits / 8;
  340. }
  341. static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
  342. const BYTE* llCodeTable,
  343. const BYTE* mlCodeTable,
  344. size_t nbSeq,
  345. const ZSTD_fseCTables_t* fseTables,
  346. const ZSTD_fseCTablesMetadata_t* fseMetadata,
  347. void* workspace, size_t wkspSize,
  348. int writeEntropy)
  349. {
  350. size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
  351. size_t cSeqSizeEstimate = 0;
  352. if (nbSeq == 0) return sequencesSectionHeaderSize;
  353. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
  354. nbSeq, fseTables->offcodeCTable, NULL,
  355. OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
  356. workspace, wkspSize);
  357. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
  358. nbSeq, fseTables->litlengthCTable, LL_bits,
  359. LL_defaultNorm, LL_defaultNormLog, MaxLL,
  360. workspace, wkspSize);
  361. cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
  362. nbSeq, fseTables->matchlengthCTable, ML_bits,
  363. ML_defaultNorm, ML_defaultNormLog, MaxML,
  364. workspace, wkspSize);
  365. if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
  366. return cSeqSizeEstimate + sequencesSectionHeaderSize;
  367. }
  368. typedef struct {
  369. size_t estLitSize;
  370. size_t estBlockSize;
  371. } EstimatedBlockSize;
  372. static EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
  373. const BYTE* ofCodeTable,
  374. const BYTE* llCodeTable,
  375. const BYTE* mlCodeTable,
  376. size_t nbSeq,
  377. const ZSTD_entropyCTables_t* entropy,
  378. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  379. void* workspace, size_t wkspSize,
  380. int writeLitEntropy, int writeSeqEntropy)
  381. {
  382. EstimatedBlockSize ebs;
  383. ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize,
  384. &entropy->huf, &entropyMetadata->hufMetadata,
  385. workspace, wkspSize, writeLitEntropy);
  386. ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
  387. nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
  388. workspace, wkspSize, writeSeqEntropy);
  389. ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize;
  390. return ebs;
  391. }
  392. static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)
  393. {
  394. if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle)
  395. return 1;
  396. if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle)
  397. return 1;
  398. if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle)
  399. return 1;
  400. return 0;
  401. }
  402. static size_t countLiterals(SeqStore_t const* seqStore, const SeqDef* sp, size_t seqCount)
  403. {
  404. size_t n, total = 0;
  405. assert(sp != NULL);
  406. for (n=0; n<seqCount; n++) {
  407. total += ZSTD_getSequenceLength(seqStore, sp+n).litLength;
  408. }
  409. DEBUGLOG(6, "countLiterals for %zu sequences from %p => %zu bytes", seqCount, (const void*)sp, total);
  410. return total;
  411. }
  412. #define BYTESCALE 256
  413. static size_t sizeBlockSequences(const SeqDef* sp, size_t nbSeqs,
  414. size_t targetBudget, size_t avgLitCost, size_t avgSeqCost,
  415. int firstSubBlock)
  416. {
  417. size_t n, budget = 0, inSize=0;
  418. /* entropy headers */
  419. size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */
  420. assert(firstSubBlock==0 || firstSubBlock==1);
  421. budget += headerSize;
  422. /* first sequence => at least one sequence*/
  423. budget += sp[0].litLength * avgLitCost + avgSeqCost;
  424. if (budget > targetBudget) return 1;
  425. inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH);
  426. /* loop over sequences */
  427. for (n=1; n<nbSeqs; n++) {
  428. size_t currentCost = sp[n].litLength * avgLitCost + avgSeqCost;
  429. budget += currentCost;
  430. inSize += sp[n].litLength + (sp[n].mlBase+MINMATCH);
  431. /* stop when sub-block budget is reached */
  432. if ( (budget > targetBudget)
  433. /* though continue to expand until the sub-block is deemed compressible */
  434. && (budget < inSize * BYTESCALE) )
  435. break;
  436. }
  437. return n;
  438. }
  439. /* ZSTD_compressSubBlock_multi() :
  440. * Breaks super-block into multiple sub-blocks and compresses them.
  441. * Entropy will be written into the first block.
  442. * The following blocks use repeat_mode to compress.
  443. * Sub-blocks are all compressed, except the last one when beneficial.
  444. * @return : compressed size of the super block (which features multiple ZSTD blocks)
  445. * or 0 if it failed to compress. */
  446. static size_t ZSTD_compressSubBlock_multi(const SeqStore_t* seqStorePtr,
  447. const ZSTD_compressedBlockState_t* prevCBlock,
  448. ZSTD_compressedBlockState_t* nextCBlock,
  449. const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
  450. const ZSTD_CCtx_params* cctxParams,
  451. void* dst, size_t dstCapacity,
  452. const void* src, size_t srcSize,
  453. const int bmi2, U32 lastBlock,
  454. void* workspace, size_t wkspSize)
  455. {
  456. const SeqDef* const sstart = seqStorePtr->sequencesStart;
  457. const SeqDef* const send = seqStorePtr->sequences;
  458. const SeqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */
  459. size_t const nbSeqs = (size_t)(send - sstart);
  460. const BYTE* const lstart = seqStorePtr->litStart;
  461. const BYTE* const lend = seqStorePtr->lit;
  462. const BYTE* lp = lstart;
  463. size_t const nbLiterals = (size_t)(lend - lstart);
  464. BYTE const* ip = (BYTE const*)src;
  465. BYTE const* const iend = ip + srcSize;
  466. BYTE* const ostart = (BYTE*)dst;
  467. BYTE* const oend = ostart + dstCapacity;
  468. BYTE* op = ostart;
  469. const BYTE* llCodePtr = seqStorePtr->llCode;
  470. const BYTE* mlCodePtr = seqStorePtr->mlCode;
  471. const BYTE* ofCodePtr = seqStorePtr->ofCode;
  472. size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */
  473. size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);
  474. int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed);
  475. int writeSeqEntropy = 1;
  476. DEBUGLOG(5, "ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)",
  477. (unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart));
  478. /* let's start by a general estimation for the full block */
  479. if (nbSeqs > 0) {
  480. EstimatedBlockSize const ebs =
  481. ZSTD_estimateSubBlockSize(lp, nbLiterals,
  482. ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,
  483. &nextCBlock->entropy, entropyMetadata,
  484. workspace, wkspSize,
  485. writeLitEntropy, writeSeqEntropy);
  486. /* quick estimation */
  487. size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE;
  488. size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs;
  489. const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1);
  490. size_t n, avgBlockBudget, blockBudgetSupp=0;
  491. avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks;
  492. DEBUGLOG(5, "estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes",
  493. (unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE,
  494. (unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE);
  495. /* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately
  496. * this will result in the production of a single uncompressed block covering @srcSize.*/
  497. if (ebs.estBlockSize > srcSize) return 0;
  498. /* compress and write sub-blocks */
  499. assert(nbSubBlocks>0);
  500. for (n=0; n < nbSubBlocks-1; n++) {
  501. /* determine nb of sequences for current sub-block + nbLiterals from next sequence */
  502. size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp),
  503. avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0);
  504. /* if reached last sequence : break to last sub-block (simplification) */
  505. assert(seqCount <= (size_t)(send-sp));
  506. if (sp + seqCount == send) break;
  507. assert(seqCount > 0);
  508. /* compress sub-block */
  509. { int litEntropyWritten = 0;
  510. int seqEntropyWritten = 0;
  511. size_t litSize = countLiterals(seqStorePtr, sp, seqCount);
  512. const size_t decompressedSize =
  513. ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0);
  514. size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
  515. sp, seqCount,
  516. lp, litSize,
  517. llCodePtr, mlCodePtr, ofCodePtr,
  518. cctxParams,
  519. op, (size_t)(oend-op),
  520. bmi2, writeLitEntropy, writeSeqEntropy,
  521. &litEntropyWritten, &seqEntropyWritten,
  522. 0);
  523. FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
  524. /* check compressibility, update state components */
  525. if (cSize > 0 && cSize < decompressedSize) {
  526. DEBUGLOG(5, "Committed sub-block compressing %u bytes => %u bytes",
  527. (unsigned)decompressedSize, (unsigned)cSize);
  528. assert(ip + decompressedSize <= iend);
  529. ip += decompressedSize;
  530. lp += litSize;
  531. op += cSize;
  532. llCodePtr += seqCount;
  533. mlCodePtr += seqCount;
  534. ofCodePtr += seqCount;
  535. /* Entropy only needs to be written once */
  536. if (litEntropyWritten) {
  537. writeLitEntropy = 0;
  538. }
  539. if (seqEntropyWritten) {
  540. writeSeqEntropy = 0;
  541. }
  542. sp += seqCount;
  543. blockBudgetSupp = 0;
  544. } }
  545. /* otherwise : do not compress yet, coalesce current sub-block with following one */
  546. }
  547. } /* if (nbSeqs > 0) */
  548. /* write last block */
  549. DEBUGLOG(5, "Generate last sub-block: %u sequences remaining", (unsigned)(send - sp));
  550. { int litEntropyWritten = 0;
  551. int seqEntropyWritten = 0;
  552. size_t litSize = (size_t)(lend - lp);
  553. size_t seqCount = (size_t)(send - sp);
  554. const size_t decompressedSize =
  555. ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1);
  556. size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,
  557. sp, seqCount,
  558. lp, litSize,
  559. llCodePtr, mlCodePtr, ofCodePtr,
  560. cctxParams,
  561. op, (size_t)(oend-op),
  562. bmi2, writeLitEntropy, writeSeqEntropy,
  563. &litEntropyWritten, &seqEntropyWritten,
  564. lastBlock);
  565. FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed");
  566. /* update pointers, the nb of literals borrowed from next sequence must be preserved */
  567. if (cSize > 0 && cSize < decompressedSize) {
  568. DEBUGLOG(5, "Last sub-block compressed %u bytes => %u bytes",
  569. (unsigned)decompressedSize, (unsigned)cSize);
  570. assert(ip + decompressedSize <= iend);
  571. ip += decompressedSize;
  572. lp += litSize;
  573. op += cSize;
  574. llCodePtr += seqCount;
  575. mlCodePtr += seqCount;
  576. ofCodePtr += seqCount;
  577. /* Entropy only needs to be written once */
  578. if (litEntropyWritten) {
  579. writeLitEntropy = 0;
  580. }
  581. if (seqEntropyWritten) {
  582. writeSeqEntropy = 0;
  583. }
  584. sp += seqCount;
  585. }
  586. }
  587. if (writeLitEntropy) {
  588. DEBUGLOG(5, "Literal entropy tables were never written");
  589. ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
  590. }
  591. if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
  592. /* If we haven't written our entropy tables, then we've violated our contract and
  593. * must emit an uncompressed block.
  594. */
  595. DEBUGLOG(5, "Sequence entropy tables were never written => cancel, emit an uncompressed block");
  596. return 0;
  597. }
  598. if (ip < iend) {
  599. /* some data left : last part of the block sent uncompressed */
  600. size_t const rSize = (size_t)((iend - ip));
  601. size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock);
  602. DEBUGLOG(5, "Generate last uncompressed sub-block of %u bytes", (unsigned)(rSize));
  603. FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
  604. assert(cSize != 0);
  605. op += cSize;
  606. /* We have to regenerate the repcodes because we've skipped some sequences */
  607. if (sp < send) {
  608. const SeqDef* seq;
  609. Repcodes_t rep;
  610. ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
  611. for (seq = sstart; seq < sp; ++seq) {
  612. ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
  613. }
  614. ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
  615. }
  616. }
  617. DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u",
  618. (unsigned)(op-ostart));
  619. return (size_t)(op-ostart);
  620. }
  621. size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
  622. void* dst, size_t dstCapacity,
  623. const void* src, size_t srcSize,
  624. unsigned lastBlock)
  625. {
  626. ZSTD_entropyCTablesMetadata_t entropyMetadata;
  627. FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,
  628. &zc->blockState.prevCBlock->entropy,
  629. &zc->blockState.nextCBlock->entropy,
  630. &zc->appliedParams,
  631. &entropyMetadata,
  632. zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */), "");
  633. return ZSTD_compressSubBlock_multi(&zc->seqStore,
  634. zc->blockState.prevCBlock,
  635. zc->blockState.nextCBlock,
  636. &entropyMetadata,
  637. &zc->appliedParams,
  638. dst, dstCapacity,
  639. src, srcSize,
  640. zc->bmi2, lastBlock,
  641. zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */);
  642. }