2 * Copyright (c) 2017-present, Facebook, Inc.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
19 #include "zstd_internal.h"
22 // Direct access to internal compression functions is required
23 #include "zstd_compress.c"
25 #define XXH_STATIC_LINKING_ONLY
26 #include "xxhash.h" /* XXH64 */
29 #define MIN(a, b) ((a) < (b) ? (a) : (b))
34 #define MAX_PATH PATH_MAX
40 /*-************************************
42 **************************************/
43 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
44 #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
45 static U32 g_displayLevel = 0;
47 #define DISPLAYUPDATE(...) \
49 if ((clockSpan(g_displayClock) > g_refreshRate) || \
50 (g_displayLevel >= 4)) { \
51 g_displayClock = clock(); \
52 DISPLAY(__VA_ARGS__); \
53 if (g_displayLevel >= 4) fflush(stderr); \
56 static const clock_t g_refreshRate = CLOCKS_PER_SEC / 6;
57 static clock_t g_displayClock = 0;
59 static clock_t clockSpan(clock_t cStart)
61 return clock() - cStart; /* works even when overflow; max span ~ 30mn */
64 #define CHECKERR(code) \
66 if (ZSTD_isError(code)) { \
67 DISPLAY("Error occurred while generating data: %s\n", \
68 ZSTD_getErrorName(code)); \
73 /*-*******************************************************
75 *********************************************************/
76 #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
78 static unsigned RAND(unsigned* src)
80 #define RAND_rotl32(x,r) ((x << r) | (x >> (32 - r)))
81 static const U32 prime1 = 2654435761U;
82 static const U32 prime2 = 2246822519U;
86 rand32 = RAND_rotl32(rand32, 13);
88 return RAND_rotl32(rand32, 27);
92 #define DISTSIZE (8192)
94 /* Write `size` bytes into `ptr`, all of which are less than or equal to `maxSymb` */
95 static void RAND_bufferMaxSymb(U32* seed, void* ptr, size_t size, int maxSymb)
100 for (i = 0; i < size; i++) {
101 op[i] = (BYTE) (RAND(seed) % (maxSymb + 1));
105 /* Write `size` random bytes into `ptr` */
106 static void RAND_buffer(U32* seed, void* ptr, size_t size)
111 for (i = 0; i + 4 <= size; i += 4) {
112 MEM_writeLE32(op + i, RAND(seed));
114 for (; i < size; i++) {
115 op[i] = RAND(seed) & 0xff;
119 /* Write `size` bytes into `ptr` following the distribution `dist` */
120 static void RAND_bufferDist(U32* seed, BYTE* dist, void* ptr, size_t size)
125 for (i = 0; i < size; i++) {
126 op[i] = dist[RAND(seed) % DISTSIZE];
130 /* Generate a random distribution where the frequency of each symbol follows a
131 * geometric distribution defined by `weight`
132 * `dist` should have size at least `DISTSIZE` */
133 static void RAND_genDist(U32* seed, BYTE* dist, double weight)
136 size_t statesLeft = DISTSIZE;
137 BYTE symb = (BYTE) (RAND(seed) % 256);
138 BYTE step = (BYTE) ((RAND(seed) % 256) | 1); /* force it to be odd so it's relatively prime to 256 */
140 while (i < DISTSIZE) {
141 size_t states = ((size_t)(weight * statesLeft)) + 1;
143 for (j = 0; j < states && i < DISTSIZE; j++, i++) {
148 statesLeft -= states;
152 /* Generates a random number in the range [min, max) */
153 static inline U32 RAND_range(U32* seed, U32 min, U32 max)
155 return (RAND(seed) % (max-min)) + min;
158 #define ROUND(x) ((U32)(x + 0.5))
160 /* Generates a random number in an exponential distribution with mean `mean` */
161 static double RAND_exp(U32* seed, double mean)
163 double const u = RAND(seed) / (double) UINT_MAX;
164 return log(1-u) * (-mean);
167 /*-*******************************************************
168 * Constants and Structs
169 *********************************************************/
170 const char *BLOCK_TYPES[] = {"raw", "rle", "compressed"};
172 #define MAX_DECOMPRESSED_SIZE_LOG 20
173 #define MAX_DECOMPRESSED_SIZE (1ULL << MAX_DECOMPRESSED_SIZE_LOG)
175 #define MAX_WINDOW_LOG 22 /* Recommended support is 8MB, so limit to 4MB + mantissa */
176 #define MAX_BLOCK_SIZE (128ULL * 1024)
178 #define MIN_SEQ_LEN (3)
179 #define MAX_NB_SEQ ((MAX_BLOCK_SIZE + MIN_SEQ_LEN - 1) / MIN_SEQ_LEN)
181 BYTE CONTENT_BUFFER[MAX_DECOMPRESSED_SIZE];
182 BYTE FRAME_BUFFER[MAX_DECOMPRESSED_SIZE * 2];
183 BYTE LITERAL_BUFFER[MAX_BLOCK_SIZE];
185 seqDef SEQUENCE_BUFFER[MAX_NB_SEQ];
186 BYTE SEQUENCE_LITERAL_BUFFER[MAX_BLOCK_SIZE]; /* storeSeq expects a place to copy literals to */
187 BYTE SEQUENCE_LLCODE[MAX_BLOCK_SIZE];
188 BYTE SEQUENCE_MLCODE[MAX_BLOCK_SIZE];
189 BYTE SEQUENCE_OFCODE[MAX_BLOCK_SIZE];
194 size_t contentSize; /* 0 means unknown (unless contentSize == windowSize == 0) */
195 unsigned windowSize; /* contentSize >= windowSize means single segment */
198 /* For repeat modes */
200 U32 rep[ZSTD_REP_NUM];
203 /* the distribution used in the previous block for repeat mode */
204 BYTE hufDist[DISTSIZE];
205 U32 hufTable [256]; /* HUF_CElt is an incomplete type */
208 FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
209 FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
210 FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
212 /* Symbols that were present in the previous distribution, for use with
214 BYTE litlengthSymbolSet[36];
215 BYTE offsetSymbolSet[29];
216 BYTE matchlengthSymbolSet[53];
228 frameHeader_t header;
231 cblockStats_t oldStats; /* so they can be rolled back if uncompressible */
234 /*-*******************************************************
235 * Generator Functions
236 *********************************************************/
239 int contentSize; /* force the content size to be present */
240 } opts; /* advanced options on generation */
242 /* Generate and write a random frame header */
243 static void writeFrameHeader(U32* seed, frame_t* frame)
245 BYTE* const op = frame->data;
251 int singleSegment = 0;
252 int contentSizeFlag = 0;
255 memset(&fh, 0, sizeof(fh));
257 /* generate window size */
259 /* Follow window algorithm from specification */
260 int const exponent = RAND(seed) % (MAX_WINDOW_LOG - 10);
261 int const mantissa = RAND(seed) % 8;
262 windowByte = (BYTE) ((exponent << 3) | mantissa);
263 fh.windowSize = (1U << (exponent + 10));
264 fh.windowSize += fh.windowSize / 8 * mantissa;
268 /* Generate random content size */
270 if (RAND(seed) & 7) {
271 /* do content of at least 128 bytes */
272 highBit = 1ULL << RAND_range(seed, 7, MAX_DECOMPRESSED_SIZE_LOG);
273 } else if (RAND(seed) & 3) {
274 /* do small content */
275 highBit = 1ULL << RAND_range(seed, 0, 7);
280 fh.contentSize = highBit ? highBit + (RAND(seed) % highBit) : 0;
282 /* provide size sometimes */
283 contentSizeFlag = opts.contentSize | (RAND(seed) & 1);
285 if (contentSizeFlag && (fh.contentSize == 0 || !(RAND(seed) & 7))) {
286 /* do single segment sometimes */
287 fh.windowSize = (U32) fh.contentSize;
292 if (contentSizeFlag) {
293 /* Determine how large fcs field has to be */
294 int minFcsCode = (fh.contentSize >= 256) +
295 (fh.contentSize >= 65536 + 256) +
296 (fh.contentSize > 0xFFFFFFFFU);
297 if (!singleSegment && !minFcsCode) {
300 fcsCode = minFcsCode + (RAND(seed) % (4 - minFcsCode));
301 if (fcsCode == 1 && fh.contentSize < 256) fcsCode++;
304 /* write out the header */
305 MEM_writeLE32(op + pos, ZSTD_MAGICNUMBER);
309 BYTE const frameHeaderDescriptor =
310 (BYTE) ((fcsCode << 6) | (singleSegment << 5) | (1 << 2));
311 op[pos++] = frameHeaderDescriptor;
314 if (!singleSegment) {
315 op[pos++] = windowByte;
318 if (contentSizeFlag) {
320 default: /* Impossible */
321 case 0: op[pos++] = (BYTE) fh.contentSize; break;
322 case 1: MEM_writeLE16(op + pos, (U16) (fh.contentSize - 256)); pos += 2; break;
323 case 2: MEM_writeLE32(op + pos, (U32) fh.contentSize); pos += 4; break;
324 case 3: MEM_writeLE64(op + pos, (U64) fh.contentSize); pos += 8; break;
328 DISPLAYLEVEL(2, " frame content size:\t%u\n", (U32)fh.contentSize);
329 DISPLAYLEVEL(2, " frame window size:\t%u\n", fh.windowSize);
330 DISPLAYLEVEL(2, " content size flag:\t%d\n", contentSizeFlag);
331 DISPLAYLEVEL(2, " single segment flag:\t%d\n", singleSegment);
333 frame->data = op + pos;
337 /* Write a literal block in either raw or RLE form, return the literals size */
338 static size_t writeLiteralsBlockSimple(U32* seed, frame_t* frame, size_t contentSize)
340 BYTE* op = (BYTE*)frame->data;
341 int const type = RAND(seed) % 2;
342 int const sizeFormatDesc = RAND(seed) % 8;
344 size_t maxLitSize = MIN(contentSize, MAX_BLOCK_SIZE);
346 if (sizeFormatDesc == 0) {
347 /* Size_FormatDesc = ?0 */
348 maxLitSize = MIN(maxLitSize, 31);
349 } else if (sizeFormatDesc <= 4) {
350 /* Size_FormatDesc = 01 */
351 maxLitSize = MIN(maxLitSize, 4095);
353 /* Size_Format = 11 */
354 maxLitSize = MIN(maxLitSize, 1048575);
357 litSize = RAND(seed) % (maxLitSize + 1);
358 if (frame->src == frame->srcStart && litSize == 0) {
359 litSize = 1; /* no empty literals if there's nothing preceding this block */
361 if (litSize + 3 > contentSize) {
362 litSize = contentSize; /* no matches shorter than 3 are allowed */
364 /* use smallest size format that fits */
366 op[0] = (type | (0 << 2) | (litSize << 3)) & 0xff;
368 } else if (litSize < 4096) {
369 op[0] = (type | (1 << 2) | (litSize << 4)) & 0xff;
370 op[1] = (litSize >> 4) & 0xff;
373 op[0] = (type | (3 << 2) | (litSize << 4)) & 0xff;
374 op[1] = (litSize >> 4) & 0xff;
375 op[2] = (litSize >> 12) & 0xff;
381 DISPLAYLEVEL(4, " raw literals\n");
383 RAND_buffer(seed, LITERAL_BUFFER, litSize);
384 memcpy(op, LITERAL_BUFFER, litSize);
388 BYTE const symb = (BYTE) (RAND(seed) % 256);
390 DISPLAYLEVEL(4, " rle literals: 0x%02x\n", (U32)symb);
392 memset(LITERAL_BUFFER, symb, litSize);
402 /* Generate a Huffman header for the given source */
403 static size_t writeHufHeader(U32* seed, HUF_CElt* hufTable, void* dst, size_t dstSize,
404 const void* src, size_t srcSize)
406 BYTE* const ostart = (BYTE*)dst;
409 unsigned huffLog = 11;
410 U32 maxSymbolValue = 255;
412 U32 count[HUF_SYMBOLVALUE_MAX+1];
414 /* Scan input and build symbol stats */
415 { size_t const largest = FSE_count_wksp (count, &maxSymbolValue, (const BYTE*)src, srcSize, WKSP);
416 if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 0; } /* single symbol, rle */
417 if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */
420 /* Build Huffman Tree */
421 /* Max Huffman log is 11, min is highbit(maxSymbolValue)+1 */
422 huffLog = RAND_range(seed, ZSTD_highbit32(maxSymbolValue)+1, huffLog+1);
423 DISPLAYLEVEL(6, " huffman log: %u\n", huffLog);
424 { size_t const maxBits = HUF_buildCTable_wksp (hufTable, count, maxSymbolValue, huffLog, WKSP, sizeof(WKSP));
426 huffLog = (U32)maxBits;
429 /* Write table description header */
430 { size_t const hSize = HUF_writeCTable (op, dstSize, hufTable, maxSymbolValue, huffLog);
431 if (hSize + 12 >= srcSize) return 0; /* not useful to try compression */
438 /* Write a Huffman coded literals block and return the litearls size */
439 static size_t writeLiteralsBlockCompressed(U32* seed, frame_t* frame, size_t contentSize)
441 BYTE* origop = (BYTE*)frame->data;
442 BYTE* opend = (BYTE*)frame->dataEnd;
444 BYTE* const ostart = origop;
445 int const sizeFormat = RAND(seed) % 4;
447 size_t hufHeaderSize = 0;
448 size_t compressedSize = 0;
449 size_t maxLitSize = MIN(contentSize-3, MAX_BLOCK_SIZE);
451 symbolEncodingType_e hType;
453 if (contentSize < 64) {
454 /* make sure we get reasonably-sized literals for compression */
455 return ERROR(GENERIC);
458 DISPLAYLEVEL(4, " compressed literals\n");
460 switch (sizeFormat) {
461 case 0: /* fall through, size is the same as case 1 */
463 maxLitSize = MIN(maxLitSize, 1023);
467 maxLitSize = MIN(maxLitSize, 16383);
471 maxLitSize = MIN(maxLitSize, 262143);
474 default:; /* impossible */
480 litSize = RAND(seed) % (maxLitSize + 1);
481 } while (litSize < 32); /* avoid small literal sizes */
482 if (litSize + 3 > contentSize) {
483 litSize = contentSize; /* no matches shorter than 3 are allowed */
486 /* most of the time generate a new distribution */
487 if ((RAND(seed) & 3) || !frame->stats.hufInit) {
489 if (RAND(seed) & 3) {
490 /* add 10 to ensure some compressability */
491 double const weight = ((RAND(seed) % 90) + 10) / 100.0;
493 DISPLAYLEVEL(5, " distribution weight: %d%%\n",
494 (int)(weight * 100));
496 RAND_genDist(seed, frame->stats.hufDist, weight);
498 /* sometimes do restricted range literals to force
499 * non-huffman headers */
500 DISPLAYLEVEL(5, " small range literals\n");
501 RAND_bufferMaxSymb(seed, frame->stats.hufDist, DISTSIZE,
504 RAND_bufferDist(seed, frame->stats.hufDist, LITERAL_BUFFER,
507 /* generate the header from the distribution instead of the
508 * actual data to avoid bugs with symbols that were in the
509 * distribution but never showed up in the output */
510 hufHeaderSize = writeHufHeader(
511 seed, (HUF_CElt*)frame->stats.hufTable, op, opend - op,
512 frame->stats.hufDist, DISTSIZE);
513 CHECKERR(hufHeaderSize);
514 /* repeat until a valid header is written */
515 } while (hufHeaderSize == 0);
517 hType = set_compressed;
519 frame->stats.hufInit = 1;
521 /* repeat the distribution/table from last time */
522 DISPLAYLEVEL(5, " huffman repeat stats\n");
523 RAND_bufferDist(seed, frame->stats.hufDist, LITERAL_BUFFER,
532 ? HUF_compress1X_usingCTable(
533 op, opend - op, LITERAL_BUFFER, litSize,
534 (HUF_CElt*)frame->stats.hufTable)
535 : HUF_compress4X_usingCTable(
536 op, opend - op, LITERAL_BUFFER, litSize,
537 (HUF_CElt*)frame->stats.hufTable);
538 CHECKERR(compressedSize);
539 /* this only occurs when it could not compress or similar */
540 } while (compressedSize <= 0);
542 op += compressedSize;
544 compressedSize += hufHeaderSize;
545 DISPLAYLEVEL(5, " regenerated size: %u\n", (U32)litSize);
546 DISPLAYLEVEL(5, " compressed size: %u\n", (U32)compressedSize);
547 if (compressedSize >= litSize) {
548 DISPLAYLEVEL(5, " trying again\n");
549 /* if we have to try again, reset the stats so we don't accidentally
550 * try to repeat a distribution we just made */
551 frame->stats = frame->oldStats;
558 switch (sizeFormat) {
559 case 0: /* fall through, size is the same as case 1 */
561 U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |
562 ((U32)compressedSize << 14);
563 MEM_writeLE24(ostart, header);
567 U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |
568 ((U32)compressedSize << 18);
569 MEM_writeLE32(ostart, header);
573 U32 const header = hType | (sizeFormat << 2) | ((U32)litSize << 4) |
574 ((U32)compressedSize << 22);
575 MEM_writeLE32(ostart, header);
576 ostart[4] = (BYTE)(compressedSize >> 10);
579 default:; /* impossible */
586 static size_t writeLiteralsBlock(U32* seed, frame_t* frame, size_t contentSize)
588 /* only do compressed for larger segments to avoid compressibility issues */
589 if (RAND(seed) & 7 && contentSize >= 64) {
590 return writeLiteralsBlockCompressed(seed, frame, contentSize);
592 return writeLiteralsBlockSimple(seed, frame, contentSize);
596 static inline void initSeqStore(seqStore_t *seqStore) {
597 seqStore->sequencesStart = SEQUENCE_BUFFER;
598 seqStore->litStart = SEQUENCE_LITERAL_BUFFER;
599 seqStore->llCode = SEQUENCE_LLCODE;
600 seqStore->mlCode = SEQUENCE_MLCODE;
601 seqStore->ofCode = SEQUENCE_OFCODE;
603 ZSTD_resetSeqStore(seqStore);
606 /* Randomly generate sequence commands */
607 static U32 generateSequences(U32* seed, frame_t* frame, seqStore_t* seqStore,
608 size_t contentSize, size_t literalsSize)
610 /* The total length of all the matches */
611 size_t const remainingMatch = contentSize - literalsSize;
612 size_t excessMatch = 0;
613 U32 numSequences = 0;
618 const BYTE* literals = LITERAL_BUFFER;
619 BYTE* srcPtr = frame->src;
621 if (literalsSize != contentSize) {
622 /* each match must be at least MIN_SEQ_LEN, so this is the maximum
623 * number of sequences we can have */
624 U32 const maxSequences = (U32)remainingMatch / MIN_SEQ_LEN;
625 numSequences = (RAND(seed) % maxSequences) + 1;
627 /* the extra match lengths we have to allocate to each sequence */
628 excessMatch = remainingMatch - numSequences * MIN_SEQ_LEN;
631 DISPLAYLEVEL(5, " total match lengths: %u\n", (U32)remainingMatch);
633 for (i = 0; i < numSequences; i++) {
634 /* Generate match and literal lengths by exponential distribution to
635 * ensure nice numbers */
638 ROUND(RAND_exp(seed, excessMatch / (double)(numSequences - i)));
641 ? ROUND(RAND_exp(seed,
643 (double)(numSequences - i)))
645 /* actual offset, code to send, and point to copy up to when shifting
646 * codes in the repeat offsets history */
647 U32 offset, offsetCode, repIndex;
650 matchLen = (U32) MIN(matchLen, excessMatch + MIN_SEQ_LEN);
651 literalLen = MIN(literalLen, (U32) literalsSize);
652 if (i == 0 && srcPtr == frame->srcStart && literalLen == 0) literalLen = 1;
653 if (i + 1 == numSequences) matchLen = MIN_SEQ_LEN + (U32) excessMatch;
655 memcpy(srcPtr, literals, literalLen);
656 srcPtr += literalLen;
659 if (RAND(seed) & 7) {
660 /* do a normal offset */
661 offset = (RAND(seed) %
662 MIN(frame->header.windowSize,
663 (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart))) +
665 offsetCode = offset + ZSTD_REP_MOVE;
668 /* do a repeat offset */
669 offsetCode = RAND(seed) % 3;
670 if (literalLen > 0) {
671 offset = frame->stats.rep[offsetCode];
672 repIndex = offsetCode;
675 offset = offsetCode == 2 ? frame->stats.rep[0] - 1
676 : frame->stats.rep[offsetCode + 1];
677 repIndex = MIN(2, offsetCode + 1);
680 } while (offset > (size_t)((BYTE*)srcPtr - (BYTE*)frame->srcStart) || offset == 0);
683 for (j = 0; j < matchLen; j++) {
684 *srcPtr = *(srcPtr-offset);
690 for (r = repIndex; r > 0; r--) {
691 frame->stats.rep[r] = frame->stats.rep[r - 1];
693 frame->stats.rep[0] = offset;
696 DISPLAYLEVEL(6, " LL: %5u OF: %5u ML: %5u", literalLen, offset, matchLen);
697 DISPLAYLEVEL(7, " srcPos: %8u seqNb: %3u",
698 (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart), i);
699 DISPLAYLEVEL(6, "\n");
700 if (offsetCode < 3) {
701 DISPLAYLEVEL(7, " repeat offset: %d\n", repIndex);
703 /* use libzstd sequence handling */
704 ZSTD_storeSeq(seqStore, literalLen, literals, offsetCode,
705 matchLen - MINMATCH);
707 literalsSize -= literalLen;
708 excessMatch -= (matchLen - MIN_SEQ_LEN);
709 literals += literalLen;
712 memcpy(srcPtr, literals, literalsSize);
713 srcPtr += literalsSize;
714 DISPLAYLEVEL(6, " excess literals: %5u", (U32)literalsSize);
715 DISPLAYLEVEL(7, " srcPos: %8u", (U32)((BYTE*)srcPtr - (BYTE*)frame->srcStart));
716 DISPLAYLEVEL(6, "\n");
721 static void initSymbolSet(const BYTE* symbols, size_t len, BYTE* set, BYTE maxSymbolValue)
725 memset(set, 0, (size_t)maxSymbolValue+1);
727 for (i = 0; i < len; i++) {
732 static int isSymbolSubset(const BYTE* symbols, size_t len, const BYTE* set, BYTE maxSymbolValue)
736 for (i = 0; i < len; i++) {
737 if (symbols[i] > maxSymbolValue || !set[symbols[i]]) {
744 static size_t writeSequences(U32* seed, frame_t* frame, seqStore_t* seqStorePtr,
747 /* This code is mostly copied from ZSTD_compressSequences in zstd_compress.c */
750 FSE_CTable* CTable_LitLength = frame->stats.litlengthCTable;
751 FSE_CTable* CTable_OffsetBits = frame->stats.offcodeCTable;
752 FSE_CTable* CTable_MatchLength = frame->stats.matchlengthCTable;
753 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
754 const seqDef* const sequences = seqStorePtr->sequencesStart;
755 const BYTE* const ofCodeTable = seqStorePtr->ofCode;
756 const BYTE* const llCodeTable = seqStorePtr->llCode;
757 const BYTE* const mlCodeTable = seqStorePtr->mlCode;
758 BYTE* const oend = (BYTE*)frame->dataEnd;
759 BYTE* op = (BYTE*)frame->data;
761 BYTE scratchBuffer[1<<MAX(MLFSELog,LLFSELog)];
763 /* literals compressing block removed so that can be done separately */
765 /* Sequences Header */
766 if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
767 if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
768 else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
769 else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
771 /* seqHead : flags for FSE encoding type */
780 /* convert length/distances into codes */
781 ZSTD_seqToCodes(seqStorePtr);
783 /* CTable for Literal Lengths */
785 size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, WKSP);
786 if (mostFrequent == nbSeq) {
787 /* do RLE if we have the chance */
788 *op++ = llCodeTable[0];
789 FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
791 } else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
792 isSymbolSubset(llCodeTable, nbSeq,
793 frame->stats.litlengthSymbolSet, 35)) {
794 /* maybe do repeat mode if we're allowed to */
796 } else if (!(RAND(seed) & 3)) {
797 /* maybe use the default distribution */
798 FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
801 /* fall back on a full table */
802 size_t nbSeq_1 = nbSeq;
803 const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
804 if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
805 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
806 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
807 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
809 FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
810 LLtype = set_compressed;
813 /* CTable for Offsets */
814 /* see Literal Lengths for descriptions of mode choices */
816 size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, WKSP);
817 if (mostFrequent == nbSeq) {
818 *op++ = ofCodeTable[0];
819 FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
821 } else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
822 isSymbolSubset(ofCodeTable, nbSeq,
823 frame->stats.offsetSymbolSet, 28)) {
824 Offtype = set_repeat;
825 } else if (!(RAND(seed) & 3)) {
826 FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
829 size_t nbSeq_1 = nbSeq;
830 const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
831 if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
832 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
833 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
834 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
836 FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
837 Offtype = set_compressed;
840 /* CTable for MatchLengths */
841 /* see Literal Lengths for descriptions of mode choices */
843 size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, WKSP);
844 if (mostFrequent == nbSeq) {
845 *op++ = *mlCodeTable;
846 FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
848 } else if (frame->stats.fseInit && !(RAND(seed) & 3) &&
849 isSymbolSubset(mlCodeTable, nbSeq,
850 frame->stats.matchlengthSymbolSet, 52)) {
852 } else if (!(RAND(seed) & 3)) {
853 /* sometimes do default distribution */
854 FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer));
857 /* fall back on table */
858 size_t nbSeq_1 = nbSeq;
859 const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
860 if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
861 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
862 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
863 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
865 FSE_buildCTable_wksp(CTable_MatchLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
866 MLtype = set_compressed;
868 frame->stats.fseInit = 1;
869 initSymbolSet(llCodeTable, nbSeq, frame->stats.litlengthSymbolSet, 35);
870 initSymbolSet(ofCodeTable, nbSeq, frame->stats.offsetSymbolSet, 28);
871 initSymbolSet(mlCodeTable, nbSeq, frame->stats.matchlengthSymbolSet, 52);
873 DISPLAYLEVEL(5, " LL type: %d OF type: %d ML type: %d\n", LLtype, Offtype, MLtype);
875 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
877 /* Encoding Sequences */
878 { BIT_CStream_t blockStream;
879 FSE_CState_t stateMatchLength;
880 FSE_CState_t stateOffsetBits;
881 FSE_CState_t stateLitLength;
883 CHECK_E(BIT_initCStream(&blockStream, op, oend-op), dstSize_tooSmall); /* not enough space remaining */
886 FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
887 FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
888 FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
889 BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
890 if (MEM_32bits()) BIT_flushBits(&blockStream);
891 BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
892 if (MEM_32bits()) BIT_flushBits(&blockStream);
893 BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
894 BIT_flushBits(&blockStream);
897 for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
898 BYTE const llCode = llCodeTable[n];
899 BYTE const ofCode = ofCodeTable[n];
900 BYTE const mlCode = mlCodeTable[n];
901 U32 const llBits = LL_bits[llCode];
902 U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
903 U32 const mlBits = ML_bits[mlCode];
905 FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
906 FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
907 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
908 FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
909 if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
910 BIT_flushBits(&blockStream); /* (7)*/
911 BIT_addBits(&blockStream, sequences[n].litLength, llBits);
912 if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
913 BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
914 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
915 BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
916 BIT_flushBits(&blockStream); /* (7)*/
919 FSE_flushCState(&blockStream, &stateMatchLength);
920 FSE_flushCState(&blockStream, &stateOffsetBits);
921 FSE_flushCState(&blockStream, &stateLitLength);
923 { size_t const streamSize = BIT_closeCStream(&blockStream);
924 if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
933 static size_t writeSequencesBlock(U32* seed, frame_t* frame, size_t contentSize,
940 initSeqStore(&seqStore);
942 /* randomly generate sequences */
943 numSequences = generateSequences(seed, frame, &seqStore, contentSize, literalsSize);
944 /* write them out to the frame data */
945 CHECKERR(writeSequences(seed, frame, &seqStore, numSequences));
950 static size_t writeCompressedBlock(U32* seed, frame_t* frame, size_t contentSize)
952 BYTE* const blockStart = (BYTE*)frame->data;
956 DISPLAYLEVEL(4, " compressed block:\n");
958 literalsSize = writeLiteralsBlock(seed, frame, contentSize);
960 DISPLAYLEVEL(4, " literals size: %u\n", (U32)literalsSize);
962 nbSeq = writeSequencesBlock(seed, frame, contentSize, literalsSize);
964 DISPLAYLEVEL(4, " number of sequences: %u\n", (U32)nbSeq);
966 return (BYTE*)frame->data - blockStart;
969 static void writeBlock(U32* seed, frame_t* frame, size_t contentSize,
972 int const blockTypeDesc = RAND(seed) % 8;
976 BYTE *const header = (BYTE*)frame->data;
977 BYTE *op = header + 3;
979 DISPLAYLEVEL(3, " block:\n");
980 DISPLAYLEVEL(3, " block content size: %u\n", (U32)contentSize);
981 DISPLAYLEVEL(3, " last block: %s\n", lastBlock ? "yes" : "no");
983 if (blockTypeDesc == 0) {
986 RAND_buffer(seed, frame->src, contentSize);
987 memcpy(op, frame->src, contentSize);
991 blockSize = contentSize;
992 } else if (blockTypeDesc == 1) {
994 BYTE const symbol = RAND(seed) & 0xff;
997 memset(frame->src, symbol, contentSize);
1001 blockSize = contentSize;
1003 /* compressed, most common */
1004 size_t compressedSize;
1007 frame->oldStats = frame->stats;
1010 compressedSize = writeCompressedBlock(seed, frame, contentSize);
1011 if (compressedSize > contentSize) {
1013 memcpy(op, frame->src, contentSize);
1016 blockSize = contentSize; /* fall back on raw block if data doesn't
1019 frame->stats = frame->oldStats; /* don't update the stats */
1021 op += compressedSize;
1022 blockSize = compressedSize;
1025 frame->src = (BYTE*)frame->src + contentSize;
1027 DISPLAYLEVEL(3, " block type: %s\n", BLOCK_TYPES[blockType]);
1028 DISPLAYLEVEL(3, " block size field: %u\n", (U32)blockSize);
1030 header[0] = (BYTE) ((lastBlock | (blockType << 1) | (blockSize << 3)) & 0xff);
1031 MEM_writeLE16(header + 1, (U16) (blockSize >> 5));
1036 static void writeBlocks(U32* seed, frame_t* frame)
1038 size_t contentLeft = frame->header.contentSize;
1039 size_t const maxBlockSize = MIN(MAX_BLOCK_SIZE, frame->header.windowSize);
1041 /* 1 in 4 chance of ending frame */
1042 int const lastBlock = contentLeft > maxBlockSize ? 0 : !(RAND(seed) & 3);
1043 size_t blockContentSize;
1045 blockContentSize = contentLeft;
1047 if (contentLeft > 0 && (RAND(seed) & 7)) {
1048 /* some variable size blocks */
1049 blockContentSize = RAND(seed) % (MIN(maxBlockSize, contentLeft)+1);
1050 } else if (contentLeft > maxBlockSize && (RAND(seed) & 1)) {
1051 /* some full size blocks */
1052 blockContentSize = maxBlockSize;
1054 /* some empty blocks */
1055 blockContentSize = 0;
1059 writeBlock(seed, frame, blockContentSize, lastBlock);
1061 contentLeft -= blockContentSize;
1062 if (lastBlock) break;
1066 static void writeChecksum(frame_t* frame)
1068 /* write checksum so implementations can verify their output */
1069 U64 digest = XXH64(frame->srcStart, (BYTE*)frame->src-(BYTE*)frame->srcStart, 0);
1070 DISPLAYLEVEL(2, " checksum: %08x\n", (U32)digest);
1071 MEM_writeLE32(frame->data, (U32)digest);
1072 frame->data = (BYTE*)frame->data + 4;
1075 static void outputBuffer(const void* buf, size_t size, const char* const path)
1077 /* write data out to file */
1078 const BYTE* ip = (const BYTE*)buf;
1081 out = fopen(path, "wb");
1086 fprintf(stderr, "Failed to open file at %s: ", path);
1092 size_t fsize = size;
1094 while (written < fsize) {
1095 written += fwrite(ip + written, 1, fsize - written, out);
1097 fprintf(stderr, "Failed to write to file at %s: ", path);
1109 static void initFrame(frame_t* fr)
1111 memset(fr, 0, sizeof(*fr));
1112 fr->data = fr->dataStart = FRAME_BUFFER;
1113 fr->dataEnd = FRAME_BUFFER + sizeof(FRAME_BUFFER);
1114 fr->src = fr->srcStart = CONTENT_BUFFER;
1115 fr->srcEnd = CONTENT_BUFFER + sizeof(CONTENT_BUFFER);
1117 /* init repeat codes */
1118 fr->stats.rep[0] = 1;
1119 fr->stats.rep[1] = 4;
1120 fr->stats.rep[2] = 8;
1123 /* Return the final seed */
1124 static U32 generateFrame(U32 seed, frame_t* fr)
1126 /* generate a complete frame */
1127 DISPLAYLEVEL(1, "frame seed: %u\n", seed);
1131 writeFrameHeader(&seed, fr);
1132 writeBlocks(&seed, fr);
1138 /*-*******************************************************
1140 *********************************************************/
1142 BYTE DECOMPRESSED_BUFFER[MAX_DECOMPRESSED_SIZE];
1144 static size_t testDecodeSimple(frame_t* fr)
1146 /* test decoding the generated data with the simple API */
1147 size_t const ret = ZSTD_decompress(DECOMPRESSED_BUFFER, MAX_DECOMPRESSED_SIZE,
1148 fr->dataStart, (BYTE*)fr->data - (BYTE*)fr->dataStart);
1150 if (ZSTD_isError(ret)) return ret;
1152 if (memcmp(DECOMPRESSED_BUFFER, fr->srcStart,
1153 (BYTE*)fr->src - (BYTE*)fr->srcStart) != 0) {
1154 return ERROR(corruption_detected);
1160 static size_t testDecodeStreaming(frame_t* fr)
1162 /* test decoding the generated data with the streaming API */
1163 ZSTD_DStream* zd = ZSTD_createDStream();
1168 if (!zd) return ERROR(memory_allocation);
1170 in.src = fr->dataStart;
1172 in.size = (BYTE*)fr->data - (BYTE*)fr->dataStart;
1174 out.dst = DECOMPRESSED_BUFFER;
1176 out.size = ZSTD_DStreamOutSize();
1178 ZSTD_initDStream(zd);
1180 ret = ZSTD_decompressStream(zd, &out, &in);
1181 if (ZSTD_isError(ret)) goto cleanup; /* error */
1182 if (ret == 0) break; /* frame is done */
1184 /* force decoding to be done in chunks */
1185 out.size += MIN(ZSTD_DStreamOutSize(), MAX_DECOMPRESSED_SIZE - out.size);
1190 if (memcmp(out.dst, fr->srcStart, out.pos) != 0) {
1191 return ERROR(corruption_detected);
1195 ZSTD_freeDStream(zd);
1199 static int runTestMode(U32 seed, unsigned numFiles, unsigned const testDurationS)
1203 clock_t const startClock = clock();
1204 clock_t const maxClockSpan = testDurationS * CLOCKS_PER_SEC;
1206 if (numFiles == 0 && !testDurationS) numFiles = 1;
1208 DISPLAY("seed: %u\n", seed);
1210 for (fnum = 0; fnum < numFiles || clockSpan(startClock) < maxClockSpan; fnum++) {
1213 if (fnum < numFiles)
1214 DISPLAYUPDATE("\r%u/%u ", fnum, numFiles);
1216 DISPLAYUPDATE("\r%u ", fnum);
1218 seed = generateFrame(seed, &fr);
1220 { size_t const r = testDecodeSimple(&fr);
1221 if (ZSTD_isError(r)) {
1222 DISPLAY("Error in simple mode on test seed %u: %s\n", seed + fnum,
1223 ZSTD_getErrorName(r));
1227 { size_t const r = testDecodeStreaming(&fr);
1228 if (ZSTD_isError(r)) {
1229 DISPLAY("Error in streaming mode on test seed %u: %s\n", seed + fnum,
1230 ZSTD_getErrorName(r));
1236 DISPLAY("\r%u tests completed: ", fnum);
1242 /*-*******************************************************
1244 *********************************************************/
1246 static int generateFile(U32 seed, const char* const path,
1247 const char* const origPath)
1251 DISPLAY("seed: %u\n", seed);
1253 generateFrame(seed, &fr);
1255 outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, path);
1257 outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, origPath);
1262 static int generateCorpus(U32 seed, unsigned numFiles, const char* const path,
1263 const char* const origPath)
1265 char outPath[MAX_PATH];
1268 DISPLAY("seed: %u\n", seed);
1270 for (fnum = 0; fnum < numFiles; fnum++) {
1273 DISPLAYUPDATE("\r%u/%u ", fnum, numFiles);
1275 seed = generateFrame(seed, &fr);
1277 if (snprintf(outPath, MAX_PATH, "%s/z%06u.zst", path, fnum) + 1 > MAX_PATH) {
1278 DISPLAY("Error: path too long\n");
1281 outputBuffer(fr.dataStart, (BYTE*)fr.data - (BYTE*)fr.dataStart, outPath);
1284 if (snprintf(outPath, MAX_PATH, "%s/z%06u", origPath, fnum) + 1 > MAX_PATH) {
1285 DISPLAY("Error: path too long\n");
1288 outputBuffer(fr.srcStart, (BYTE*)fr.src - (BYTE*)fr.srcStart, outPath);
1292 DISPLAY("\r%u/%u \n", fnum, numFiles);
1298 /*_*******************************************************
1300 *********************************************************/
1301 static U32 makeSeed(void)
1303 U32 t = (U32) time(NULL);
1304 return XXH32(&t, sizeof(t), 0) % 65536;
1307 static unsigned readInt(const char** argument)
1310 while ((**argument>='0') && (**argument<='9')) {
1312 val += **argument - '0';
1318 static void usage(const char* programName)
1320 DISPLAY( "Usage :\n");
1321 DISPLAY( " %s [args]\n", programName);
1323 DISPLAY( "Arguments :\n");
1324 DISPLAY( " -p<path> : select output path (default:stdout)\n");
1325 DISPLAY( " in multiple files mode this should be a directory\n");
1326 DISPLAY( " -o<path> : select path to output original file (default:no output)\n");
1327 DISPLAY( " in multiple files mode this should be a directory\n");
1328 DISPLAY( " -s# : select seed (default:random based on time)\n");
1329 DISPLAY( " -n# : number of files to generate (default:1)\n");
1330 DISPLAY( " -t : activate test mode (test files against libzstd instead of outputting them)\n");
1331 DISPLAY( " -T# : length of time to run tests for\n");
1332 DISPLAY( " -v : increase verbosity level (default:0, max:7)\n");
1333 DISPLAY( " -h/H : display help/long help and exit\n");
1336 static void advancedUsage(const char* programName)
1340 DISPLAY( "Advanced arguments :\n");
1341 DISPLAY( " --content-size : always include the content size in the frame header\n");
1344 int main(int argc, char** argv)
1348 unsigned numFiles = 0;
1349 unsigned testDuration = 0;
1351 const char* path = NULL;
1352 const char* origPath = NULL;
1356 /* Check command line */
1357 for (argNb=1; argNb<argc; argNb++) {
1358 const char* argument = argv[argNb];
1359 if(!argument) continue; /* Protection if argument empty */
1361 /* Handle commands. Aggregated commands are allowed */
1362 if (argument[0]=='-') {
1364 while (*argument!=0) {
1371 advancedUsage(argv[0]);
1380 seed = readInt(&argument);
1384 numFiles = readInt(&argument);
1388 testDuration = readInt(&argument);
1389 if (*argument == 'm') {
1392 if (*argument == 'n') argument++;
1397 origPath = argument;
1398 argument += strlen(argument);
1403 argument += strlen(argument);
1411 if (strcmp(argument, "content-size") == 0) {
1412 opts.contentSize = 1;
1414 advancedUsage(argv[0]);
1417 argument += strlen(argument);
1422 } } } } /* for (argNb=1; argNb<argc; argNb++) */
1429 return runTestMode(seed, numFiles, testDuration);
1432 DISPLAY("Error: -T requires test mode (-t)\n\n");
1439 DISPLAY("Error: path is required in file generation mode\n");
1444 if (numFiles == 0) {
1445 return generateFile(seed, path, origPath);
1447 return generateCorpus(seed, numFiles, path, origPath);