From 779ea729535d1421ac4451db296b0685f8f22f7e Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Tue, 15 Oct 2019 07:49:13 +0100 Subject: [PATCH 001/402] Adding --file=FILE feature --- programs/util.c | 229 +++++++++++++++++++++++++++++++++++++++++++++ programs/util.h | 36 ++++++- programs/zstdcli.c | 72 +++++++++++++- 3 files changed, 335 insertions(+), 2 deletions(-) diff --git a/programs/util.c b/programs/util.c index 3988295d45b..caadf40e3dc 100644 --- a/programs/util.c +++ b/programs/util.c @@ -163,6 +163,235 @@ U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbF return error ? UTIL_FILESIZE_UNKNOWN : total; } + +int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { + if (feof(file)) { + UTIL_DISPLAYLEVEL(1, "[ERROR] end of file reached and need to read\n"); + return -1; + } + UTIL_DISPLAY("[TRACE] read line\n"); + + char* fgetsCheck = fgets(buf, len, file); + + if(fgetsCheck == NULL || fgetsCheck != buf) { + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readLineFromFile] fgets has a problem check: %s buf: %s \n", + fgetsCheck == NULL ? "NULL" : fgetsCheck, buf); + return -1; + } + + UTIL_DISPLAY("[TRACE] length of Line: %d\n" , (int)strlen(buf)); + return (int) strlen(buf)-1; /* -1 to ignore '\n' character */ +} + +/* Warning: inputFileSize should be less than or equal buf capacity and buf should be initialized*/ +static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileName) { + + if(!buf) { + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); + return -1; + } + + UTIL_DISPLAY("[TRACE] open file\n"); + FILE* inputFile = fopen(inputFileName, "r"); + int nbFiles = -1; + + if(!inputFile) { + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't open file to read input file names.\n"); + return -1; + } + + unsigned pos = 0; + for(nbFiles=0; !feof(inputFile) ; ) { + if(UTIL_readLineFromFile(buf+pos, inputFileSize, inputFile) > 0) { + int len = (int) strlen(buf+pos); + buf[pos+len-1] = '\0'; /* replace '\n' with '\0'*/ + UTIL_DISPLAY("[TRACE] line: %s\n", buf+pos); + pos += len; + ++nbFiles; + } + else + UTIL_DISPLAY("[TRACE] ignored line: %s", buf+pos); + } + + fclose(inputFile); + + if(pos > inputFileSize) return -1; + + return nbFiles; +} + +/*Note: buf is not freed in case function successfully created table because filesTable->fileNames[0] = buf*/ +FileNamesTable* +UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { + + UTIL_DISPLAY("file check\n"); + if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName)) + return NULL; + + UTIL_DISPLAY("[TRACE] start function readFileNamesTableFromFile\n"); + U64 inputFileSize = UTIL_getFileSize(inputFileName) + 1; /* (+1) to add '\0' at the end of last filename */ + + if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE) + return NULL; + + char* buf = (char*) malloc(inputFileSize * sizeof(char)); + if(!buf) { + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); + return NULL; + } + + int nbFiles = readFromFile(buf, inputFileSize, inputFileName); + + if(nbFiles <= 0) { + free(buf); + return NULL; + } + + UTIL_DISPLAY("[TRACE] file closed with %d read lines\n", nbFiles); + + FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + if(!filesTable) { + free(buf); + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create table for files.\n"); + return NULL; + } + + filesTable->tableSize = nbFiles; + filesTable->fileNames = (const char**) malloc((nbFiles+1) * sizeof(char*)); + + UTIL_DISPLAY("[TRACE] Start migration\n"); + + size_t i = 0, pos = 0; + for(i = 0, pos = 0; i < nbFiles; ++i) { + filesTable->fileNames[i] = buf+pos; + UTIL_DISPLAY("[TRACE] file %zu: %s\n", i, filesTable->fileNames[i]); + pos += strlen(buf+pos)+1; + } + + UTIL_DISPLAY("[TRACE] migration done\n"); + + + UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %lu\n", pos, inputFileSize); + if(pos > inputFileSize){ + UTIL_freeFileNamesTable(filesTable); + if(buf) free(buf); + return NULL; + } + + filesTable->buf = buf; + UTIL_DISPLAY("[TRACE] finished reading\n"); + + return filesTable; +} + +void UTIL_freeFileNamesTable(FileNamesTable* table) { + if(table) { + if(table->fileNames) { + if(table->buf) + free(table->buf); + free(table->fileNames); + } + free(table); + } +} + +static size_t getTotalTableSize(FileNamesTable* table) { + size_t i = 0, totalSize = 0; + for(i = 0 ; i < table->tableSize && table->fileNames[i] ; ++i) { + totalSize += strlen(table->fileNames[i]) + 1; /* +1 to add '\0' at the end of each fileName */ + } + + return totalSize; +} + +FileNamesTable* +UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { + UTIL_DISPLAY("[TRACE] Start concatenation\n"); + unsigned newTableIdx = 0, idx1 = 0, idx2 = 0; + size_t i = 0; + + FileNamesTable* newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + + if(!newTable) { + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); + return NULL; + } + + int newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); + UTIL_DISPLAY("[TRACE] buf total size is: %d\n", newTotalTableSize); + + char* buf = (char*) malloc(newTotalTableSize * sizeof(char)); + if(!buf) { + UTIL_freeFileNamesTable(newTable); + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create buf for concatenation output.\n"); + return NULL; + } + + for(i = 0; i < newTotalTableSize ; ++i) buf[i] = '\0'; + + newTable->tableSize = table1->tableSize + table2->tableSize; + newTable->fileNames = (const char **) malloc(newTable->tableSize * sizeof(char*)); + + if(!newTable->fileNames) { + UTIL_freeFileNamesTable(newTable); + if(buf) free(buf); + UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); + return NULL; + } + + for (i = 0; i < newTable->tableSize; ++i) + newTable->fileNames[i] = NULL; + + UTIL_DISPLAY("[TRACE] add table1 concatenation of size %zu\n", table1->tableSize); + size_t pos = 0; + for( ; idx1 < table1->tableSize && table1->fileNames[idx1] && pos < newTotalTableSize; ++idx1, ++newTableIdx) { + size_t curLen = strlen(table1->fileNames[idx1]); + memcpy(buf+pos, table1->fileNames[idx1], curLen); + newTable->fileNames[newTableIdx] = buf+pos; + pos += curLen+1; + } + + UTIL_DISPLAY("[TRACE] table1 actual size %u\n", idx1); + + UTIL_DISPLAY("[TRACE] add table2 concatenation of size %zu\n", table2->tableSize); + for( ; idx2 < table2->tableSize && table2->fileNames[idx2] && pos < newTotalTableSize ; ++idx2, ++newTableIdx) { + size_t curLen = strlen(table2->fileNames[idx2]); + memcpy(buf+pos, table2->fileNames[idx2], curLen); + newTable->fileNames[newTableIdx] = buf+pos; + pos += curLen+1; + } + + if(pos > newTotalTableSize) { + UTIL_freeFileNamesTable(newTable); + if(buf) free(buf); + return NULL; + } + + UTIL_DISPLAY("[TRACE] table2 actual size %u\n", idx2); + UTIL_DISPLAY("[TRACE] new table actual size %u\n", newTableIdx); + + assert(newTableIdx == newTable->tableSize || newTable->fileNames[newTableIdx] == NULL); + + UTIL_DISPLAY("[TRACE] table1:\n"); + for(idx1 = 0 ; idx1 < table1->tableSize && table1->fileNames[idx1] ; ++idx1) + UTIL_DISPLAY("[TRACE] %u %s\n", idx1, table1->fileNames[idx1]); + + UTIL_DISPLAY("[TRACE] table2:\n"); + for(idx2 = 0 ; idx2 < table2->tableSize && table2->fileNames[idx2] ; ++idx2) + UTIL_DISPLAY("[TRACE] %u %s\n", idx2, table2->fileNames[idx2]); + + UTIL_DISPLAY("[TRACE] new table:\n"); + for(newTableIdx = 0; newTableIdx < newTable->tableSize && newTable->fileNames[newTableIdx] ; ++newTableIdx) + UTIL_DISPLAY("[TRACE] %u %s\n", newTableIdx, newTable->fileNames[newTableIdx]); + + UTIL_freeFileNamesTable(table1); + UTIL_freeFileNamesTable(table2); + UTIL_DISPLAY("[TRACE] concatenation finished\n"); + + newTable->buf = buf; + return newTable; +} + #ifdef _WIN32 int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks) { diff --git a/programs/util.h b/programs/util.h index 0080b63c7a1..33a6d6dea90 100644 --- a/programs/util.h +++ b/programs/util.h @@ -90,7 +90,7 @@ extern "C" { * Constants ***************************************/ #define LIST_SIZE_INCREASE (8*1024) - +#define MAX_FILE_OF_FILE_NAMES_SIZE (1<<20)*50 /*-**************************************** * Compiler specifics @@ -140,6 +140,40 @@ U32 UTIL_isLink(const char* infilename); U64 UTIL_getFileSize(const char* infilename); U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles); +/*! UTIL_readLineFromFile(char* buf, size_t len, File* file): + * @return : int. size next line in file or -1 in case of file ends + * function reads next line in the file + * Will also modify `*file`, advancing it to position where it stopped reading. + */ +int UTIL_readLineFromFile(char* buf, size_t len, FILE* file); + +/*Note: tableSize is denotes the total capacity of table*/ +typedef struct +{ + const char** fileNames; + char* buf; + size_t tableSize; +} FileNamesTable; + +/*! UTIL_readFileNamesTableFromFile(const char* inputFileName) : + * @return : char** the fileNamesTable or NULL in case of not regular file or file doesn't exist. + * reads fileNamesTable from input fileName. + * Note: inputFileSize should be less than or equal 50MB + */ +FileNamesTable* UTIL_createFileNamesTable_fromFileName(const char* inputFileName); + +/*! UTIL_freeFileNamesTable(FileNamesTable* table) : + * This function takes an buffered based table and frees it. + * @return : void. + */ +void UTIL_freeFileNamesTable(FileNamesTable* table); + +/*! UTIL_concatenateTwoTables(FileNamesTable* table1,FileNamesTable* table2): + * takes table1, its maxSize, table2 and its maxSize, free them and returns its concatenation. + * @return : FileNamesTable* concatenation of two tables + * note table1 and table2 will be freed + */ +FileNamesTable* UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2); /* * A modified version of realloc(). diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 98df728a98b..e8e17fff190 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -565,6 +565,7 @@ int main(int argCount, const char* argv[]) nextArgumentIsMaxDict = 0, nextArgumentIsDictID = 0, nextArgumentsAreFiles = 0, + isTableBufferBased = 0, nextEntryIsDictionary = 0, operationResult = 0, separateFiles = 0, @@ -582,7 +583,9 @@ int main(int argCount, const char* argv[]) int cLevelLast = -1000000000; unsigned recursive = 0; unsigned memLimit = 0; - const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); /* argCount >= 1 */ + unsigned filenameTableSize = argCount; + const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*)); /* argCount >= 1 */ + char* tableBuf = NULL; unsigned filenameIdx = 0; const char* programName = argv[0]; const char* outFileName = NULL; @@ -791,6 +794,66 @@ int main(int argCount, const char* argv[]) continue; } #endif + + if (longCommandWArg(&argument, "--file=")) { + DISPLAYLEVEL(4, "[TRACE] argument catched\n"); + const char* fileName = argument; + DISPLAYLEVEL(4, "[TRACE] fileName: %s\n", fileName); + if(!UTIL_fileExist(fileName) || !UTIL_isRegularFile(fileName)){ + DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", fileName); + CLEAN_RETURN(badusage(programName)); + } + + DISPLAYLEVEL(4, "[TRACE] call read function\n"); + FileNamesTable* extendedTable = UTIL_createFileNamesTable_fromFileName(fileName); + if(!extendedTable) { + CLEAN_RETURN(badusage(programName)); + } + + DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); + DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); + size_t extendedTableSize = extendedTable->tableSize; + const char ** extendedFileNamesTable = extendedTable->fileNames; + + int i = 0; + for(i = 0; i < extendedTableSize; ++i) + printf("%s\n",extendedFileNamesTable[i]); + + DISPLAYLEVEL(4, "[TRACE] call concatenation function\n"); + DISPLAYLEVEL(4, "[TRACE] filenameidx: %d\n", filenameIdx); + + for(i = filenameIdx; i < filenameTableSize ; ++i) + filenameTable[i] = NULL; + + FileNamesTable* curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + if(!curTable) { + UTIL_freeFileNamesTable(extendedTable); + CLEAN_RETURN(badusage(programName)); + } + + curTable->fileNames = filenameTable; + curTable->tableSize = filenameTableSize; + curTable->buf = tableBuf; + + FileNamesTable* concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable); + if(!concatenatedTables) { + UTIL_freeFileNamesTable(curTable); + UTIL_freeFileNamesTable(extendedTable); + CLEAN_RETURN(badusage(programName)); + } + + filenameTable = concatenatedTables->fileNames; + filenameTableSize = concatenatedTables->tableSize; + tableBuf = concatenatedTables->buf; + + filenameIdx += extendedTableSize; + free(concatenatedTables); + isTableBufferBased = 1; + + DISPLAYLEVEL(1, "[TRACE] call concatenation function is finished\n"); + + continue; + } /* fall-through, will trigger bad_usage() later on */ } @@ -1193,6 +1256,13 @@ int main(int argCount, const char* argv[]) _end: FIO_freePreferences(prefs); + if(filenameTable) { + if(isTableBufferBased && tableBuf){ + free(tableBuf); + } + } + + if (main_pause) waitEnter(); #ifdef UTIL_HAS_CREATEFILELIST if (extendedFileList) From eda7946a3682896c6301d5846226b7938a1e2243 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Tue, 22 Oct 2019 23:21:54 -0700 Subject: [PATCH 002/402] Take ZSTD_parameters as a const pointer Fixes: #1637 --- lib/compress/zstd_compress.c | 20 ++++++++++---------- lib/dictBuilder/zdict.c | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ded25d8dab9..ae52fa607ed 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -248,12 +248,12 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete /* ZSTD_assignParamsToCCtxParams() : * params is presumed valid at this stage */ static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams( - const ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) + const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) { ZSTD_CCtx_params ret = *cctxParams; - assert(!ZSTD_checkCParams(params.cParams)); - ret.cParams = params.cParams; - ret.fParams = params.fParams; + assert(!ZSTD_checkCParams(params->cParams)); + ret.cParams = params->cParams; + ret.fParams = params->fParams; ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ return ret; } @@ -2969,7 +2969,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, ZSTD_parameters params, unsigned long long pledgedSrcSize) { ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); + ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL /*cdict*/, @@ -2980,7 +2980,7 @@ size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t di { ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); + ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered); @@ -3064,7 +3064,7 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict,size_t dictSize, - ZSTD_parameters params) + const ZSTD_parameters* params) { ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); @@ -3088,7 +3088,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, dst, dstCapacity, src, srcSize, dict, dictSize, - params); + ¶ms); } /* Internal */ @@ -3113,7 +3113,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, int compressionLevel) { ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0); - ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); + ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); assert(params.fParams.contentSizeFlag == 1); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams); } @@ -3560,7 +3560,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) ); - zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, params); + zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, ¶ms); FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) ); return 0; } diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 4a263d822d8..1e7f8343209 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -588,12 +588,12 @@ typedef struct #define MAXREPOFFSET 1024 -static void ZDICT_countEStats(EStats_ress_t esr, ZSTD_parameters params, +static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params, unsigned* countLit, unsigned* offsetcodeCount, unsigned* matchlengthCount, unsigned* litlengthCount, U32* repOffsets, const void* src, size_t srcSize, U32 notificationLevel) { - size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << params.cParams.windowLog); + size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << params->cParams.windowLog); size_t cSize; if (srcSize > blockSizeMax) srcSize = blockSizeMax; /* protection vs large samples */ @@ -731,7 +731,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, /* collect stats on all samples */ for (u=0; u Date: Wed, 23 Oct 2019 20:14:48 +0100 Subject: [PATCH 003/402] solving C90 issues in defining local variables in middle of code and comparing uncompatible types --- programs/util.c | 7 ++++--- programs/zstdcli.c | 32 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/programs/util.c b/programs/util.c index 34d3acdff7a..cb2e6410b65 100644 --- a/programs/util.c +++ b/programs/util.c @@ -251,12 +251,13 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { return NULL; } - int nbFiles = readFromFile(buf, inputFileSize, inputFileName); + int ret_nbFiles = readFromFile(buf, inputFileSize, inputFileName); - if(nbFiles <= 0) { + if(ret_nbFiles <= 0) { free(buf); return NULL; } + unsigned nbFiles = ret_nbFiles; UTIL_DISPLAY("[TRACE] file closed with %d read lines\n", nbFiles); @@ -328,7 +329,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { return NULL; } - int newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); + size_t newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); UTIL_DISPLAY("[TRACE] buf total size is: %d\n", newTotalTableSize); char* buf = (char*) malloc(newTotalTableSize * sizeof(char)); diff --git a/programs/zstdcli.c b/programs/zstdcli.c index a8cb5cce267..ade7ca00a23 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -587,6 +587,9 @@ int main(int argCount, const char* argv[]) unsigned memLimit = 0; unsigned filenameTableSize = argCount; const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*)); /* argCount >= 1 */ + FileNamesTable* extendedTable = NULL; + FileNamesTable* concatenatedTables = NULL; + FileNamesTable* curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); char* tableBuf = NULL; unsigned filenameIdx = 0; const char* programName = argv[0]; @@ -622,6 +625,9 @@ int main(int argCount, const char* argv[]) (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */ if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); } filenameTable[0] = stdinmark; + curTable->fileNames = filenameTable; + curTable->tableSize = filenameTableSize; + curTable->buf = tableBuf; g_displayOut = stderr; cLevel = init_cLevel(); programName = lastNameFromPath(programName); @@ -803,26 +809,24 @@ int main(int argCount, const char* argv[]) if (longCommandWArg(&argument, "--file=")) { DISPLAYLEVEL(4, "[TRACE] argument catched\n"); const char* fileName = argument; - DISPLAYLEVEL(4, "[TRACE] fileName: %s\n", fileName); - if(!UTIL_fileExist(fileName) || !UTIL_isRegularFile(fileName)){ - DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", fileName); + DISPLAYLEVEL(4, "[TRACE] fileName: %s\n", argument); + if(!UTIL_fileExist(fileName) || !UTIL_isRegularFile(argument)){ + DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument); CLEAN_RETURN(badusage(programName)); } DISPLAYLEVEL(4, "[TRACE] call read function\n"); - FileNamesTable* extendedTable = UTIL_createFileNamesTable_fromFileName(fileName); + extendedTable = UTIL_createFileNamesTable_fromFileName(argument); if(!extendedTable) { CLEAN_RETURN(badusage(programName)); } DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); - size_t extendedTableSize = extendedTable->tableSize; - const char ** extendedFileNamesTable = extendedTable->fileNames; - int i = 0; - for(i = 0; i < extendedTableSize; ++i) - printf("%s\n",extendedFileNamesTable[i]); + unsigned i = 0; + for(i = 0; i < extendedTable->tableSize; ++i) + printf("%s\n",extendedTable->fileNames[i]); DISPLAYLEVEL(4, "[TRACE] call concatenation function\n"); DISPLAYLEVEL(4, "[TRACE] filenameidx: %d\n", filenameIdx); @@ -830,7 +834,6 @@ int main(int argCount, const char* argv[]) for(i = filenameIdx; i < filenameTableSize ; ++i) filenameTable[i] = NULL; - FileNamesTable* curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); if(!curTable) { UTIL_freeFileNamesTable(extendedTable); CLEAN_RETURN(badusage(programName)); @@ -840,7 +843,7 @@ int main(int argCount, const char* argv[]) curTable->tableSize = filenameTableSize; curTable->buf = tableBuf; - FileNamesTable* concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable); + concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable); if(!concatenatedTables) { UTIL_freeFileNamesTable(curTable); UTIL_freeFileNamesTable(extendedTable); @@ -851,8 +854,7 @@ int main(int argCount, const char* argv[]) filenameTableSize = concatenatedTables->tableSize; tableBuf = concatenatedTables->buf; - filenameIdx += extendedTableSize; - free(concatenatedTables); + filenameIdx += extendedTable->tableSize; isTableBufferBased = 1; DISPLAYLEVEL(1, "[TRACE] call concatenation function is finished\n"); @@ -1273,7 +1275,9 @@ int main(int argCount, const char* argv[]) free(tableBuf); } } - + UTIL_freeFileNamesTable(curTable); + UTIL_freeFileNamesTable(extendedTable); + UTIL_freeFileNamesTable(concatenatedTables); if (main_pause) waitEnter(); #ifdef UTIL_HAS_CREATEFILELIST From 8cbe42fcb029e0b8c8e1c169be219f4c19be29d8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Wed, 23 Oct 2019 20:22:07 +0100 Subject: [PATCH 004/402] solving the rest of C90 issues in defining local variables in middle of code and comparing uncompatible types --- programs/util.c | 4 ++-- programs/zstdcli.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/programs/util.c b/programs/util.c index cb2e6410b65..e28e4a96b4f 100644 --- a/programs/util.c +++ b/programs/util.c @@ -283,7 +283,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { UTIL_DISPLAY("[TRACE] migration done\n"); - UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %lu\n", pos, inputFileSize); + UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %llu\n", pos, inputFileSize); if(pos > inputFileSize){ UTIL_freeFileNamesTable(filesTable); if(buf) free(buf); @@ -330,7 +330,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { } size_t newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); - UTIL_DISPLAY("[TRACE] buf total size is: %d\n", newTotalTableSize); + UTIL_DISPLAY("[TRACE] buf total size is: %zu\n", newTotalTableSize); char* buf = (char*) malloc(newTotalTableSize * sizeof(char)); if(!buf) { diff --git a/programs/zstdcli.c b/programs/zstdcli.c index ade7ca00a23..9a05cf72c79 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -808,9 +808,8 @@ int main(int argCount, const char* argv[]) if (longCommandWArg(&argument, "--file=")) { DISPLAYLEVEL(4, "[TRACE] argument catched\n"); - const char* fileName = argument; DISPLAYLEVEL(4, "[TRACE] fileName: %s\n", argument); - if(!UTIL_fileExist(fileName) || !UTIL_isRegularFile(argument)){ + if(!UTIL_fileExist(argument) || !UTIL_isRegularFile(argument)){ DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument); CLEAN_RETURN(badusage(programName)); } @@ -824,7 +823,7 @@ int main(int argCount, const char* argv[]) DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); - unsigned i = 0; + unsigned i; for(i = 0; i < extendedTable->tableSize; ++i) printf("%s\n",extendedTable->fileNames[i]); From f43e45954ff337f5e9e74686b7b2c66581506388 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 09:39:16 +0100 Subject: [PATCH 005/402] fixing memory leak issue and removing c90 issue --- programs/util.c | 3 +++ programs/zstdcli.c | 16 +++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/programs/util.c b/programs/util.c index e28e4a96b4f..7da11e2f6ba 100644 --- a/programs/util.c +++ b/programs/util.c @@ -308,6 +308,7 @@ void UTIL_freeFileNamesTable(FileNamesTable* table) { } static size_t getTotalTableSize(FileNamesTable* table) { + UTIL_DISPLAY("[TRACE] getTotalTableSize \n"); size_t i = 0, totalSize = 0; for(i = 0 ; i < table->tableSize && table->fileNames[i] ; ++i) { totalSize += strlen(table->fileNames[i]) + 1; /* +1 to add '\0' at the end of each fileName */ @@ -324,6 +325,8 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { FileNamesTable* newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + UTIL_DISPLAY("[TRACE] newTable created\n"); + if(!newTable) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); return NULL; diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 9a05cf72c79..43d496c932a 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -589,7 +589,7 @@ int main(int argCount, const char* argv[]) const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*)); /* argCount >= 1 */ FileNamesTable* extendedTable = NULL; FileNamesTable* concatenatedTables = NULL; - FileNamesTable* curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + FileNamesTable* curTable = NULL; char* tableBuf = NULL; unsigned filenameIdx = 0; const char* programName = argv[0]; @@ -625,9 +625,6 @@ int main(int argCount, const char* argv[]) (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */ if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); } filenameTable[0] = stdinmark; - curTable->fileNames = filenameTable; - curTable->tableSize = filenameTableSize; - curTable->buf = tableBuf; g_displayOut = stderr; cLevel = init_cLevel(); programName = lastNameFromPath(programName); @@ -823,15 +820,16 @@ int main(int argCount, const char* argv[]) DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); - unsigned i; - for(i = 0; i < extendedTable->tableSize; ++i) - printf("%s\n",extendedTable->fileNames[i]); DISPLAYLEVEL(4, "[TRACE] call concatenation function\n"); DISPLAYLEVEL(4, "[TRACE] filenameidx: %d\n", filenameIdx); - for(i = filenameIdx; i < filenameTableSize ; ++i) - filenameTable[i] = NULL; + // unsigned i = 0; + // for(i = filenameIdx; i < filenameTableSize ; ++i) + filenameTable[filenameIdx] = NULL; // marking end of table + + + curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); if(!curTable) { UTIL_freeFileNamesTable(extendedTable); From aefa18ee380d4b71255a7092c7260393c3aeb10a Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 10:12:51 +0100 Subject: [PATCH 006/402] fixing c90 issue in util.c --- programs/util.c | 46 ++++++++++++++++++++++++++++------------------ programs/zstdcli.c | 6 +----- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/programs/util.c b/programs/util.c index 7da11e2f6ba..a79278500b0 100644 --- a/programs/util.c +++ b/programs/util.c @@ -176,13 +176,15 @@ U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbF int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { + char* fgetsCheck = NULL; + if (feof(file)) { UTIL_DISPLAYLEVEL(1, "[ERROR] end of file reached and need to read\n"); return -1; } UTIL_DISPLAY("[TRACE] read line\n"); - char* fgetsCheck = fgets(buf, len, file); + fgetsCheck = fgets(buf, len, file); if(fgetsCheck == NULL || fgetsCheck != buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readLineFromFile] fgets has a problem check: %s buf: %s \n", @@ -197,21 +199,21 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { /* Warning: inputFileSize should be less than or equal buf capacity and buf should be initialized*/ static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileName) { + UTIL_DISPLAY("[TRACE] open file\n"); + FILE* inputFile = fopen(inputFileName, "r"); + int nbFiles = -1; + unsigned pos = 0; + if(!buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); return -1; } - UTIL_DISPLAY("[TRACE] open file\n"); - FILE* inputFile = fopen(inputFileName, "r"); - int nbFiles = -1; - if(!inputFile) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't open file to read input file names.\n"); return -1; } - unsigned pos = 0; for(nbFiles=0; !feof(inputFile) ; ) { if(UTIL_readLineFromFile(buf+pos, inputFileSize, inputFile) > 0) { int len = (int) strlen(buf+pos); @@ -234,13 +236,20 @@ static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileNa /*Note: buf is not freed in case function successfully created table because filesTable->fileNames[0] = buf*/ FileNamesTable* UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { + U64 inputFileSize = 0; + unsigned nbFiles = 0; + int ret_nbFiles = -1; + + FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable));; + + size_t i = 0, pos = 0; UTIL_DISPLAY("file check\n"); if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName)) return NULL; UTIL_DISPLAY("[TRACE] start function readFileNamesTableFromFile\n"); - U64 inputFileSize = UTIL_getFileSize(inputFileName) + 1; /* (+1) to add '\0' at the end of last filename */ + inputFileSize = UTIL_getFileSize(inputFileName) + 1; /* (+1) to add '\0' at the end of last filename */ if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE) return NULL; @@ -251,17 +260,16 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { return NULL; } - int ret_nbFiles = readFromFile(buf, inputFileSize, inputFileName); + ret_nbFiles = readFromFile(buf, inputFileSize, inputFileName); if(ret_nbFiles <= 0) { free(buf); return NULL; } - unsigned nbFiles = ret_nbFiles; + nbFiles = ret_nbFiles; UTIL_DISPLAY("[TRACE] file closed with %d read lines\n", nbFiles); - FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); if(!filesTable) { free(buf); UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create table for files.\n"); @@ -273,7 +281,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { UTIL_DISPLAY("[TRACE] Start migration\n"); - size_t i = 0, pos = 0; + for(i = 0, pos = 0; i < nbFiles; ++i) { filesTable->fileNames[i] = buf+pos; UTIL_DISPLAY("[TRACE] file %zu: %s\n", i, filesTable->fileNames[i]); @@ -283,7 +291,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { UTIL_DISPLAY("[TRACE] migration done\n"); - UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %llu\n", pos, inputFileSize); + UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %lu\n", pos, inputFileSize); if(pos > inputFileSize){ UTIL_freeFileNamesTable(filesTable); if(buf) free(buf); @@ -308,7 +316,6 @@ void UTIL_freeFileNamesTable(FileNamesTable* table) { } static size_t getTotalTableSize(FileNamesTable* table) { - UTIL_DISPLAY("[TRACE] getTotalTableSize \n"); size_t i = 0, totalSize = 0; for(i = 0 ; i < table->tableSize && table->fileNames[i] ; ++i) { totalSize += strlen(table->fileNames[i]) + 1; /* +1 to add '\0' at the end of each fileName */ @@ -319,12 +326,15 @@ static size_t getTotalTableSize(FileNamesTable* table) { FileNamesTable* UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { - UTIL_DISPLAY("[TRACE] Start concatenation\n"); unsigned newTableIdx = 0, idx1 = 0, idx2 = 0; - size_t i = 0; + size_t i = 0, pos = 0; + + size_t newTotalTableSize = 0; FileNamesTable* newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + UTIL_DISPLAY("[TRACE] Start concatenation\n"); + UTIL_DISPLAY("[TRACE] newTable created\n"); if(!newTable) { @@ -332,7 +342,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { return NULL; } - size_t newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); + newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); UTIL_DISPLAY("[TRACE] buf total size is: %zu\n", newTotalTableSize); char* buf = (char*) malloc(newTotalTableSize * sizeof(char)); @@ -358,7 +368,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { newTable->fileNames[i] = NULL; UTIL_DISPLAY("[TRACE] add table1 concatenation of size %zu\n", table1->tableSize); - size_t pos = 0; for( ; idx1 < table1->tableSize && table1->fileNames[idx1] && pos < newTotalTableSize; ++idx1, ++newTableIdx) { size_t curLen = strlen(table1->fileNames[idx1]); memcpy(buf+pos, table1->fileNames[idx1], curLen); @@ -399,11 +408,12 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { for(newTableIdx = 0; newTableIdx < newTable->tableSize && newTable->fileNames[newTableIdx] ; ++newTableIdx) UTIL_DISPLAY("[TRACE] %u %s\n", newTableIdx, newTable->fileNames[newTableIdx]); + newTable->buf = buf; + UTIL_freeFileNamesTable(table1); UTIL_freeFileNamesTable(table2); UTIL_DISPLAY("[TRACE] concatenation finished\n"); - newTable->buf = buf; return newTable; } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 43d496c932a..eaa461781e8 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -820,14 +820,10 @@ int main(int argCount, const char* argv[]) DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); - DISPLAYLEVEL(4, "[TRACE] call concatenation function\n"); DISPLAYLEVEL(4, "[TRACE] filenameidx: %d\n", filenameIdx); - // unsigned i = 0; - // for(i = filenameIdx; i < filenameTableSize ; ++i) - filenameTable[filenameIdx] = NULL; // marking end of table - + filenameTable[filenameIdx] = NULL; // marking end of table curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); From 8a9741b3ee0fbe05e9a6412abd68e76d9ac1041c Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 10:17:31 +0100 Subject: [PATCH 007/402] fixing c90 issue in util.c cont. --- programs/util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/util.c b/programs/util.c index a79278500b0..10c4fe4b6f4 100644 --- a/programs/util.c +++ b/programs/util.c @@ -199,11 +199,12 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { /* Warning: inputFileSize should be less than or equal buf capacity and buf should be initialized*/ static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileName) { - UTIL_DISPLAY("[TRACE] open file\n"); FILE* inputFile = fopen(inputFileName, "r"); int nbFiles = -1; unsigned pos = 0; + UTIL_DISPLAY("[TRACE] open file\n"); + if(!buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); return -1; @@ -239,6 +240,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { U64 inputFileSize = 0; unsigned nbFiles = 0; int ret_nbFiles = -1; + char* buf = NULL; FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable));; @@ -254,7 +256,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE) return NULL; - char* buf = (char*) malloc(inputFileSize * sizeof(char)); + buf = (char*) malloc(inputFileSize * sizeof(char)); if(!buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); return NULL; From c799f33899c58e2967708720477101548ac925a5 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 10:23:36 +0100 Subject: [PATCH 008/402] fixing c90 issue in util.c cont. again --- programs/util.c | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 10c4fe4b6f4..c79fe7d44bf 100644 --- a/programs/util.c +++ b/programs/util.c @@ -293,7 +293,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { UTIL_DISPLAY("[TRACE] migration done\n"); - UTIL_DISPLAY("[TRACE] pos %zu inputFileSize %lu\n", pos, inputFileSize); if(pos > inputFileSize){ UTIL_freeFileNamesTable(filesTable); if(buf) free(buf); From 47712c9b15b4df51e10854cea51357f2c2b015bc Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 10:30:05 +0100 Subject: [PATCH 009/402] fixing c90 issue in util.c cont. --- programs/util.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/programs/util.c b/programs/util.c index c79fe7d44bf..f3e76bf8677 100644 --- a/programs/util.c +++ b/programs/util.c @@ -241,11 +241,10 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { unsigned nbFiles = 0; int ret_nbFiles = -1; char* buf = NULL; - - FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable));; - size_t i = 0, pos = 0; + FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + UTIL_DISPLAY("file check\n"); if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName)) return NULL; @@ -329,11 +328,12 @@ FileNamesTable* UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { unsigned newTableIdx = 0, idx1 = 0, idx2 = 0; size_t i = 0, pos = 0; - size_t newTotalTableSize = 0; FileNamesTable* newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + char* buf = NULL; + UTIL_DISPLAY("[TRACE] Start concatenation\n"); UTIL_DISPLAY("[TRACE] newTable created\n"); @@ -346,7 +346,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); UTIL_DISPLAY("[TRACE] buf total size is: %zu\n", newTotalTableSize); - char* buf = (char*) malloc(newTotalTableSize * sizeof(char)); + buf = (char*) malloc(newTotalTableSize * sizeof(char)); if(!buf) { UTIL_freeFileNamesTable(newTable); UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create buf for concatenation output.\n"); From 849b8c6de8466558c687baaed9e8d5bf5ff629b8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 11:10:13 +0100 Subject: [PATCH 010/402] fixing continuous integeration errors and removing a lot of logs --- programs/util.c | 37 +------------------------------------ programs/zstdcli.c | 13 ++----------- 2 files changed, 3 insertions(+), 47 deletions(-) diff --git a/programs/util.c b/programs/util.c index f3e76bf8677..fc90e9044f8 100644 --- a/programs/util.c +++ b/programs/util.c @@ -182,9 +182,8 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { UTIL_DISPLAYLEVEL(1, "[ERROR] end of file reached and need to read\n"); return -1; } - UTIL_DISPLAY("[TRACE] read line\n"); - fgetsCheck = fgets(buf, len, file); + fgetsCheck = fgets(buf, (int) len, file); if(fgetsCheck == NULL || fgetsCheck != buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readLineFromFile] fgets has a problem check: %s buf: %s \n", @@ -192,7 +191,6 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) { return -1; } - UTIL_DISPLAY("[TRACE] length of Line: %d\n" , (int)strlen(buf)); return (int) strlen(buf)-1; /* -1 to ignore '\n' character */ } @@ -203,7 +201,6 @@ static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileNa int nbFiles = -1; unsigned pos = 0; - UTIL_DISPLAY("[TRACE] open file\n"); if(!buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); @@ -219,12 +216,9 @@ static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileNa if(UTIL_readLineFromFile(buf+pos, inputFileSize, inputFile) > 0) { int len = (int) strlen(buf+pos); buf[pos+len-1] = '\0'; /* replace '\n' with '\0'*/ - UTIL_DISPLAY("[TRACE] line: %s\n", buf+pos); pos += len; ++nbFiles; } - else - UTIL_DISPLAY("[TRACE] ignored line: %s", buf+pos); } fclose(inputFile); @@ -249,7 +243,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName)) return NULL; - UTIL_DISPLAY("[TRACE] start function readFileNamesTableFromFile\n"); inputFileSize = UTIL_getFileSize(inputFileName) + 1; /* (+1) to add '\0' at the end of last filename */ if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE) @@ -269,7 +262,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { } nbFiles = ret_nbFiles; - UTIL_DISPLAY("[TRACE] file closed with %d read lines\n", nbFiles); if(!filesTable) { free(buf); @@ -280,7 +272,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { filesTable->tableSize = nbFiles; filesTable->fileNames = (const char**) malloc((nbFiles+1) * sizeof(char*)); - UTIL_DISPLAY("[TRACE] Start migration\n"); for(i = 0, pos = 0; i < nbFiles; ++i) { @@ -289,8 +280,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { pos += strlen(buf+pos)+1; } - UTIL_DISPLAY("[TRACE] migration done\n"); - if(pos > inputFileSize){ UTIL_freeFileNamesTable(filesTable); @@ -299,7 +288,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { } filesTable->buf = buf; - UTIL_DISPLAY("[TRACE] finished reading\n"); return filesTable; } @@ -334,9 +322,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { char* buf = NULL; - UTIL_DISPLAY("[TRACE] Start concatenation\n"); - - UTIL_DISPLAY("[TRACE] newTable created\n"); if(!newTable) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); @@ -344,7 +329,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { } newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); - UTIL_DISPLAY("[TRACE] buf total size is: %zu\n", newTotalTableSize); buf = (char*) malloc(newTotalTableSize * sizeof(char)); if(!buf) { @@ -368,7 +352,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { for (i = 0; i < newTable->tableSize; ++i) newTable->fileNames[i] = NULL; - UTIL_DISPLAY("[TRACE] add table1 concatenation of size %zu\n", table1->tableSize); for( ; idx1 < table1->tableSize && table1->fileNames[idx1] && pos < newTotalTableSize; ++idx1, ++newTableIdx) { size_t curLen = strlen(table1->fileNames[idx1]); memcpy(buf+pos, table1->fileNames[idx1], curLen); @@ -376,9 +359,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { pos += curLen+1; } - UTIL_DISPLAY("[TRACE] table1 actual size %u\n", idx1); - UTIL_DISPLAY("[TRACE] add table2 concatenation of size %zu\n", table2->tableSize); for( ; idx2 < table2->tableSize && table2->fileNames[idx2] && pos < newTotalTableSize ; ++idx2, ++newTableIdx) { size_t curLen = strlen(table2->fileNames[idx2]); memcpy(buf+pos, table2->fileNames[idx2], curLen); @@ -392,28 +373,12 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { return NULL; } - UTIL_DISPLAY("[TRACE] table2 actual size %u\n", idx2); - UTIL_DISPLAY("[TRACE] new table actual size %u\n", newTableIdx); - assert(newTableIdx == newTable->tableSize || newTable->fileNames[newTableIdx] == NULL); - UTIL_DISPLAY("[TRACE] table1:\n"); - for(idx1 = 0 ; idx1 < table1->tableSize && table1->fileNames[idx1] ; ++idx1) - UTIL_DISPLAY("[TRACE] %u %s\n", idx1, table1->fileNames[idx1]); - - UTIL_DISPLAY("[TRACE] table2:\n"); - for(idx2 = 0 ; idx2 < table2->tableSize && table2->fileNames[idx2] ; ++idx2) - UTIL_DISPLAY("[TRACE] %u %s\n", idx2, table2->fileNames[idx2]); - - UTIL_DISPLAY("[TRACE] new table:\n"); - for(newTableIdx = 0; newTableIdx < newTable->tableSize && newTable->fileNames[newTableIdx] ; ++newTableIdx) - UTIL_DISPLAY("[TRACE] %u %s\n", newTableIdx, newTable->fileNames[newTableIdx]); - newTable->buf = buf; UTIL_freeFileNamesTable(table1); UTIL_freeFileNamesTable(table2); - UTIL_DISPLAY("[TRACE] concatenation finished\n"); return newTable; } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index eaa461781e8..c6146f5fe41 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -585,7 +585,7 @@ int main(int argCount, const char* argv[]) int cLevelLast = -1000000000; unsigned recursive = 0; unsigned memLimit = 0; - unsigned filenameTableSize = argCount; + size_t filenameTableSize = argCount; const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*)); /* argCount >= 1 */ FileNamesTable* extendedTable = NULL; FileNamesTable* concatenatedTables = NULL; @@ -804,24 +804,17 @@ int main(int argCount, const char* argv[]) #endif if (longCommandWArg(&argument, "--file=")) { - DISPLAYLEVEL(4, "[TRACE] argument catched\n"); - DISPLAYLEVEL(4, "[TRACE] fileName: %s\n", argument); + if(!UTIL_fileExist(argument) || !UTIL_isRegularFile(argument)){ DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument); CLEAN_RETURN(badusage(programName)); } - DISPLAYLEVEL(4, "[TRACE] call read function\n"); extendedTable = UTIL_createFileNamesTable_fromFileName(argument); if(!extendedTable) { CLEAN_RETURN(badusage(programName)); } - DISPLAYLEVEL(4, "[TRACE] call read function is finished\n"); - DISPLAYLEVEL(4, "[TRACE] extendedFileNamesTable:\n"); - - DISPLAYLEVEL(4, "[TRACE] call concatenation function\n"); - DISPLAYLEVEL(4, "[TRACE] filenameidx: %d\n", filenameIdx); filenameTable[filenameIdx] = NULL; // marking end of table @@ -850,8 +843,6 @@ int main(int argCount, const char* argv[]) filenameIdx += extendedTable->tableSize; isTableBufferBased = 1; - DISPLAYLEVEL(1, "[TRACE] call concatenation function is finished\n"); - continue; } /* fall-through, will trigger bad_usage() later on */ From 639bb46954da5ab87404b093bbdd76a9bbdebdad Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 11:35:26 +0100 Subject: [PATCH 011/402] removing extra logs --- programs/util.c | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index fc90e9044f8..febfb4ad71b 100644 --- a/programs/util.c +++ b/programs/util.c @@ -276,7 +276,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { for(i = 0, pos = 0; i < nbFiles; ++i) { filesTable->fileNames[i] = buf+pos; - UTIL_DISPLAY("[TRACE] file %zu: %s\n", i, filesTable->fileNames[i]); pos += strlen(buf+pos)+1; } From 0e6a73b1485f44e13b495481491a067851653571 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 13:51:12 +0100 Subject: [PATCH 012/402] fixing newTable issues and some warnings --- programs/util.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/programs/util.c b/programs/util.c index febfb4ad71b..74b4decc96f 100644 --- a/programs/util.c +++ b/programs/util.c @@ -237,9 +237,8 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { char* buf = NULL; size_t i = 0, pos = 0; - FileNamesTable* filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + FileNamesTable* filesTable = NULL; - UTIL_DISPLAY("file check\n"); if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName)) return NULL; @@ -262,7 +261,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { } nbFiles = ret_nbFiles; - + filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); if(!filesTable) { free(buf); UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create table for files.\n"); @@ -294,10 +293,13 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { void UTIL_freeFileNamesTable(FileNamesTable* table) { if(table) { if(table->fileNames) { - if(table->buf) - free(table->buf); free(table->fileNames); } + + if(table->buf) { + free(table->buf); + } + free(table); } } @@ -317,11 +319,13 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { size_t i = 0, pos = 0; size_t newTotalTableSize = 0; - FileNamesTable* newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + FileNamesTable* newTable = NULL; char* buf = NULL; + newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + if(!newTable) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); return NULL; @@ -372,8 +376,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { return NULL; } - assert(newTableIdx == newTable->tableSize || newTable->fileNames[newTableIdx] == NULL); - newTable->buf = buf; UTIL_freeFileNamesTable(table1); From 5e206fdd5370d5ed8c7fcf49ba9abad9d0850ed0 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 14:21:01 +0100 Subject: [PATCH 013/402] fixing some warning --- programs/util.c | 2 +- programs/util.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/util.c b/programs/util.c index 74b4decc96f..277b0cd5c27 100644 --- a/programs/util.c +++ b/programs/util.c @@ -296,7 +296,7 @@ void UTIL_freeFileNamesTable(FileNamesTable* table) { free(table->fileNames); } - if(table->buf) { + if(table && table->buf) { free(table->buf); } diff --git a/programs/util.h b/programs/util.h index f126246be40..cb01fcefe20 100644 --- a/programs/util.h +++ b/programs/util.h @@ -151,8 +151,8 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file); /*Note: tableSize is denotes the total capacity of table*/ typedef struct { - const char** fileNames; - char* buf; + const char** fileNames = NULL; + char* buf = NULL; size_t tableSize; } FileNamesTable; From cddb05ef8c0b3a169456df789d02ce5002b0f03d Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 14:42:37 +0100 Subject: [PATCH 014/402] fixing some warning --- programs/util.c | 16 ++++++++++++++-- programs/util.h | 14 ++++++++++++-- programs/zstdcli.c | 6 +----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/programs/util.c b/programs/util.c index 277b0cd5c27..7257c8a5581 100644 --- a/programs/util.c +++ b/programs/util.c @@ -261,7 +261,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { } nbFiles = ret_nbFiles; - filesTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + filesTable = UTIL_createFileNamesTable(NULL, NULL, 0); if(!filesTable) { free(buf); UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create table for files.\n"); @@ -290,6 +290,18 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { return filesTable; } +FileNamesTable* +UTIL_createFileNamesTable(const char** filenames, char* buf, size_t tableSize){ + FileNamesTable* table = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + if(!table) { + return NULL; + } + table->fileNames = filenames; + table->buf = buf; + table->tableSize = tableSize; + return table; +} + void UTIL_freeFileNamesTable(FileNamesTable* table) { if(table) { if(table->fileNames) { @@ -324,7 +336,7 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) { char* buf = NULL; - newTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + newTable = UTIL_createFileNamesTable(NULL, NULL, 0); if(!newTable) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n"); diff --git a/programs/util.h b/programs/util.h index cb01fcefe20..bd275e2c714 100644 --- a/programs/util.h +++ b/programs/util.h @@ -151,8 +151,8 @@ int UTIL_readLineFromFile(char* buf, size_t len, FILE* file); /*Note: tableSize is denotes the total capacity of table*/ typedef struct { - const char** fileNames = NULL; - char* buf = NULL; + const char** fileNames; + char* buf; size_t tableSize; } FileNamesTable; @@ -163,6 +163,16 @@ typedef struct */ FileNamesTable* UTIL_createFileNamesTable_fromFileName(const char* inputFileName); + +/*! UTIL_freeFileNamesTable(const char** filenames, char* buf, size_t tableSize) : + * This function takes an buffered based filename, buf and tableSize to create its object. + * @return : FileNamesTable* + */ + +FileNamesTable* +UTIL_createFileNamesTable(const char** filenames, char* buf, size_t tableSize); + + /*! UTIL_freeFileNamesTable(FileNamesTable* table) : * This function takes an buffered based table and frees it. * @return : void. diff --git a/programs/zstdcli.c b/programs/zstdcli.c index c6146f5fe41..99f344fcb05 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -818,17 +818,13 @@ int main(int argCount, const char* argv[]) filenameTable[filenameIdx] = NULL; // marking end of table - curTable = (FileNamesTable*) malloc(sizeof(FileNamesTable)); + curTable = UTIL_createFileNamesTable(filenameTable, tableBuf, filenameTableSize); if(!curTable) { UTIL_freeFileNamesTable(extendedTable); CLEAN_RETURN(badusage(programName)); } - curTable->fileNames = filenameTable; - curTable->tableSize = filenameTableSize; - curTable->buf = tableBuf; - concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable); if(!concatenatedTables) { UTIL_freeFileNamesTable(curTable); From 0b3096596aabcd6de0163f7d8f99a26b10f272c1 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 15:25:48 +0100 Subject: [PATCH 015/402] fixing AppVeyor errors --- programs/util.c | 2 +- programs/zstdcli.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/util.c b/programs/util.c index 7257c8a5581..21f1fe7db02 100644 --- a/programs/util.c +++ b/programs/util.c @@ -247,7 +247,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE) return NULL; - buf = (char*) malloc(inputFileSize * sizeof(char)); + buf = (char*) malloc((size_t) inputFileSize * sizeof(char)); if(!buf) { UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n"); return NULL; diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 99f344fcb05..9470473d930 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -836,7 +836,7 @@ int main(int argCount, const char* argv[]) filenameTableSize = concatenatedTables->tableSize; tableBuf = concatenatedTables->buf; - filenameIdx += extendedTable->tableSize; + filenameIdx += (unsigned) extendedTable->tableSize; isTableBufferBased = 1; continue; From 5f9e868ee858985445021261ea91ac39603c819e Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 16:20:58 +0100 Subject: [PATCH 016/402] fixing type conversion error --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 21f1fe7db02..1a202982612 100644 --- a/programs/util.c +++ b/programs/util.c @@ -253,7 +253,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) { return NULL; } - ret_nbFiles = readFromFile(buf, inputFileSize, inputFileName); + ret_nbFiles = readFromFile(buf, (size_t) inputFileSize, inputFileName); if(ret_nbFiles <= 0) { free(buf); From 5249085e114ddad2c62130bd6c07cd5d2a0115f3 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Thu, 24 Oct 2019 20:54:40 +0100 Subject: [PATCH 017/402] fixing free const char** filenamesTable --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 1a202982612..d86b7c2234d 100644 --- a/programs/util.c +++ b/programs/util.c @@ -305,7 +305,7 @@ UTIL_createFileNamesTable(const char** filenames, char* buf, size_t tableSize){ void UTIL_freeFileNamesTable(FileNamesTable* table) { if(table) { if(table->fileNames) { - free(table->fileNames); + free((void*)table->fileNames); } if(table && table->buf) { From 1faeb222b2dee12fd8eb9fe24a9bb03dff495512 Mon Sep 17 00:00:00 2001 From: Ahmed Abdellah Date: Fri, 25 Oct 2019 15:54:52 +0100 Subject: [PATCH 018/402] adding some functional tests --- tests/playTests.sh | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/playTests.sh b/tests/playTests.sh index 796a5bde921..a6998e2a6f1 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -293,6 +293,53 @@ test -f tmpOutDirDecomp/tmp2 test -f tmpOutDirDecomp/tmp1 rm -rf tmp* +println "test : compress multiple files reading them from a file, --file=FILE" +mkdir tmpInputTestDir +println "Hello world!, file1" > tmpInputTestDir/file1 +println "Hello world!, file2" > tmpInputTestDir/file2 +println tmpInputTestDir/file1 > tmp +println tmpInputTestDir/file2 >> tmp +$ZSTD -f --file=tmp +test -f tmpInputTestDir/file2.zst +test -f tmpInputTestDir/file1.zst +rm tmpInputTestDir/*.zst + +println "test : compress multiple files reading them from multiple files, --file=FILE" +println "Hello world!, file3" > tmpInputTestDir/file3 +println "Hello world!, file4" > tmpInputTestDir/file4 +println tmpInputTestDir/file3 > tmp1 +println tmpInputTestDir/file4 >> tmp1 +$ZSTD -f --file=tmp --file=tmp1 +test -f tmpInputTestDir/file1.zst +test -f tmpInputTestDir/file2.zst +test -f tmpInputTestDir/file3.zst +test -f tmpInputTestDir/file4.zst + +println "test : decompress multiple files reading them from a file, --file=FILE" +rm tmpInputTestDir/file1 +rm tmpInputTestDir/file2 +println tmpInputTestDir/file1.zst > tmpZst +println tmpInputTestDir/file2.zst >> tmpZst +$ZSTD -d -f --file=tmpZst +test -f tmpInputTestDir/file2 +test -f tmpInputTestDir/file1 + +println "test : decompress multiple files reading them from multiple files, --file=FILE" +rm tmpInputTestDir/file1 +rm tmpInputTestDir/file2 +rm tmpInputTestDir/file3 +rm tmpInputTestDir/file4 +println tmpInputTestDir/file3.zst > tmpZst1 +println tmpInputTestDir/file4.zst >> tmpZst1 +$ZSTD -d -f --file=tmpZst --file=tmpZst1 +test -f tmpInputTestDir/file1 +test -f tmpInputTestDir/file2 +test -f tmpInputTestDir/file3 +test -f tmpInputTestDir/file4 + +rm -rf tmp* + + println "\n===> Advanced compression parameters " println "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!" println "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!" From 1ead0c5d5a12f2a584c796e557699010245e278f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 25 Oct 2019 16:36:59 -0700 Subject: [PATCH 019/402] improved --file=FILE implementation pass basic tests --- doc/zstd_manual.html | 11 +- programs/util.c | 357 ++++++++++++++++++++----------------------- programs/util.h | 8 +- programs/zstdcli.c | 64 ++++---- tests/playTests.sh | 66 ++++---- 5 files changed, 241 insertions(+), 265 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 0021eec2815..21ba000ccc7 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -947,7 +947,7 @@

Streaming decompression functions


* to evolve and should be considered only in the context of extremely * advanced performance tuning. * - * Zstd currently supports the use of a CDict in two ways: + * Zstd currently supports the use of a CDict in three ways: * * - The contents of the CDict can be copied into the working context. This * means that the compression can search both the dictionary and input @@ -962,6 +962,12 @@

Streaming decompression functions


* tables. However, this model incurs no start-up cost (as long as the * working context's tables can be reused). For small inputs, this can be * faster than copying the CDict's tables. + * + * - The CDict's tables are not used at all, and instead we use the working + * context alone to reload the dictionary and use params based on the source + * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). + * This method is effective when the dictionary sizes are very small relative + * to the input size, and the input size is fairly large to begin with. * * Zstd has a simple internal heuristic that selects which strategy to use * at the beginning of a compression. However, if experimentation shows that @@ -970,7 +976,8 @@

Streaming decompression functions


*/ ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ - ZSTD_dictForceCopy = 2 /* Always copy the dictionary. */ + ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ + ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ } ZSTD_dictAttachPref_e;
typedef enum {
diff --git a/programs/util.c b/programs/util.c
index 2abb1be3a4a..57602d1a239 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -24,6 +24,32 @@ extern "C" {
 #include      /* needed for _mkdir in windows */
 #endif
 
+
+/*-****************************************
+*  Internal Macros
+******************************************/
+
+/* CONTROL is like an assert(), but is never disabled.
+ * Since it's always active, it can trigger side effects.
+ */
+#define CONTROL(c)  {         \
+    if (!(c)) {               \
+        UTIL_DISPLAYLEVEL(1, "Error : %s, %i : %s",  \
+                          __FILE__, __LINE__, #c);   \
+        abort();              \
+}   }
+
+
+/*-****************************************
+*  Console log
+******************************************/
+int g_utilDisplayLevel;
+
+
+/*-****************************************
+*  Public API
+******************************************/
+
 int UTIL_fileExist(const char* filename)
 {
     stat_t statbuf;
@@ -188,220 +214,174 @@ U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbF
 }
 
 
-int UTIL_readLineFromFile(char* buf, size_t len, FILE* file) {
-    char* fgetsCheck = NULL;
-
-    if (feof(file)) {
-      UTIL_DISPLAYLEVEL(1, "[ERROR] end of file reached and need to read\n");
-      return -1;
-    }
-
-    fgetsCheck = fgets(buf, (int) len, file);
-
-    if(fgetsCheck == NULL || fgetsCheck != buf) {
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readLineFromFile] fgets has a problem check: %s buf: %s \n",
-        fgetsCheck == NULL ? "NULL" : fgetsCheck, buf);
-      return -1;
-    }
-
-    return (int) strlen(buf)-1;   /* -1 to ignore '\n' character */
+/* condition : @file must be valid, and not have reached its end.
+ * @return : length of line written into buf, without the final '\n',
+ *           or 0, if there is no new line */
+static size_t readLineFromFile(char* buf, size_t len, FILE* file)
+{
+    fprintf(stderr, "readLineFromFile \n");
+    assert(!feof(file));
+    CONTROL( fgets(buf, (int) len, file) == buf );  /* requires success */
+    fprintf(stderr, "line = %s \n", buf);
+    if (strlen(buf)==0) return 0;
+    return strlen(buf) - (buf[strlen(buf)-1] == '\n');   /* -1 to ignore final '\n' character */
 }
 
-/* Warning: inputFileSize should be less than or equal buf capacity and buf should be initialized*/
-static int readFromFile(char* buf, size_t inputFileSize, const char* inputFileName) {
-
-  FILE* inputFile = fopen(inputFileName, "r");
-  int nbFiles = -1;
-  unsigned pos = 0;
-
+/* Conditions :
+ *   size of @inputFileName file must be < @dstCapacity
+ *   @dst must be initialized
+ * @return : nb of lines
+ *       or -1 if there's an error
+ */
+static int
+readLinesFromFile(void* dst, size_t dstCapacity,
+            const char* inputFileName)
+{
+    int nbFiles = 0;
+    unsigned pos = 0;
+    char* const buf = (char*)dst;
+    FILE* const inputFile = fopen(inputFileName, "r");
 
-  if(!buf) {
-    UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n");
-    return -1;
-  }
+    assert(dst != NULL);
 
-  if(!inputFile) {
-    UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't open file to read input file names.\n");
-    return -1;
-  }
+    fprintf(stderr, "readLinesFromFile %s \n", inputFileName);
 
-  for(nbFiles=0; !feof(inputFile) ; ) {
-    if(UTIL_readLineFromFile(buf+pos, inputFileSize, inputFile) > 0) {
-      int len = (int) strlen(buf+pos);
-      buf[pos+len-1] = '\0'; /* replace '\n' with '\0'*/
-      pos += len;
-      ++nbFiles;
+    if(!inputFile) {
+        if (g_utilDisplayLevel >= 1) perror("zstd:util:readLinesFromFile");
+        return -1;
     }
-  }
 
-  fclose(inputFile);
+    while ( !feof(inputFile) ) {
+        size_t const lineLength = readLineFromFile(buf+pos, dstCapacity-pos, inputFile);
+        if (lineLength == 0) break;
+        assert(pos + lineLength < dstCapacity);
+        buf[pos+lineLength] = '\0'; /* replace '\n' with '\0'*/
+        pos += lineLength + 1;
+        ++nbFiles;
+        fprintf(stderr, "nbFiles = %i \n", nbFiles);
+    }
 
-  if(pos > inputFileSize) return -1;
+    CONTROL( fclose(inputFile) == 0 );
 
-  return nbFiles;
+    return nbFiles;
 }
 
 /*Note: buf is not freed in case function successfully created table because filesTable->fileNames[0] = buf*/
 FileNamesTable*
-UTIL_createFileNamesTable_fromFileName(const char* inputFileName) {
-    U64 inputFileSize = 0;
-    unsigned nbFiles = 0;
-    int ret_nbFiles = -1;
-    char* buf = NULL;
-    size_t i = 0, pos = 0;
-
-    FileNamesTable* filesTable = NULL;
-
-    if(!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName))
-      return NULL;
-
-    inputFileSize = UTIL_getFileSize(inputFileName) + 1; /* (+1) to add '\0' at the end of last filename */
+UTIL_createFileNamesTable_fromFileName(const char* inputFileName)
+{
+    size_t nbFiles = 0;
+    char* buf;
+    size_t bufSize;
+    size_t pos = 0;
 
-    if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE)
-      return NULL;
+    if (!UTIL_fileExist(inputFileName) || !UTIL_isRegularFile(inputFileName))
+        return NULL;
 
-    buf = (char*) malloc((size_t) inputFileSize * sizeof(char));
-    if(!buf) {
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create buffer.\n");
-      return NULL;
+    {   U64 const inputFileSize = UTIL_getFileSize(inputFileName);
+        if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE)
+            return NULL;
+        bufSize = inputFileSize + 1; /* (+1) to add '\0' at the end of last filename */
     }
 
-    ret_nbFiles = readFromFile(buf, (size_t) inputFileSize, inputFileName);
+    buf = (char*) malloc(bufSize);
+    CONTROL( buf != NULL );
 
-    if(ret_nbFiles <= 0) {
-      free(buf);
-      return NULL;
-    }
-    nbFiles = ret_nbFiles;
+    {   int const ret_nbFiles = readLinesFromFile(buf, bufSize, inputFileName);
 
-    filesTable = UTIL_createFileNamesTable(NULL, NULL, 0);
-    if(!filesTable) {
-      free(buf);
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_readFileNamesTableFromFile] Can't create table for files.\n");
-      return NULL;
+        if (ret_nbFiles <= 0) {
+          free(buf);
+          return NULL;
+        }
+        nbFiles = (size_t)ret_nbFiles;
     }
 
-    filesTable->tableSize = nbFiles;
-    filesTable->fileNames = (const char**) malloc((nbFiles+1) * sizeof(char*));
-
+    {   const char** filenamesTable = (const char**) malloc(nbFiles * sizeof(*filenamesTable));
+        CONTROL(filenamesTable != NULL);
 
+        {   size_t fnb;
+            for (fnb = 0, pos = 0; fnb < nbFiles; fnb++) {
+                filenamesTable[fnb] = buf+pos;
+                pos += strlen(buf+pos)+1;  /* +1 for the finishing `\0` */
+        }   }
+        assert(pos <= bufSize);
 
-    for(i = 0, pos = 0; i < nbFiles; ++i) {
-      filesTable->fileNames[i] = buf+pos;
-      pos += strlen(buf+pos)+1;
+        return UTIL_createFileNamesTable(filenamesTable, nbFiles, buf);
     }
-
-
-    if(pos > inputFileSize){
-      UTIL_freeFileNamesTable(filesTable);
-      if(buf) free(buf);
-      return NULL;
-    }
-
-    filesTable->buf = buf;
-
-    return filesTable;
 }
 
 FileNamesTable*
-UTIL_createFileNamesTable(const char** filenames, char* buf, size_t tableSize){
-  FileNamesTable* table = (FileNamesTable*) malloc(sizeof(FileNamesTable));
-  if(!table) {
-    return NULL;
-  }
-  table->fileNames = filenames;
-  table->buf = buf;
-  table->tableSize = tableSize;
-  return table;
+UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf)
+{
+    FileNamesTable* const table = (FileNamesTable*) malloc(sizeof(*table));
+    if(!table) return NULL;
+    table->fileNames = filenames;
+    table->buf = buf;
+    table->tableSize = tableSize;
+    return table;
 }
 
-void UTIL_freeFileNamesTable(FileNamesTable* table) {
-  if(table) {
-    if(table->fileNames) {
-      free((void*)table->fileNames);
-    }
-
-    if(table && table->buf) {
-      free(table->buf);
-    }
-
+void UTIL_freeFileNamesTable(FileNamesTable* table)
+{
+    if (table==NULL) return;
+    free((void*)table->fileNames);
+    free(table->buf);
     free(table);
-  }
 }
 
-static size_t getTotalTableSize(FileNamesTable* table) {
-  size_t i = 0, totalSize = 0;
-  for(i = 0 ; i < table->tableSize && table->fileNames[i] ; ++i) {
-    totalSize += strlen(table->fileNames[i]) + 1; /* +1 to add '\0' at the end of each fileName */
-  }
-
-  return totalSize;
+static size_t getTotalTableSize(FileNamesTable* table)
+{
+    size_t fnb = 0, totalSize = 0;
+    for(fnb = 0 ; fnb < table->tableSize && table->fileNames[fnb] ; ++fnb) {
+        totalSize += strlen(table->fileNames[fnb]) + 1; /* +1 to add '\0' at the end of each fileName */
+    }
+    return totalSize;
 }
 
 FileNamesTable*
-UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) {
-    unsigned newTableIdx = 0, idx1 = 0, idx2 = 0;
-    size_t i = 0, pos = 0;
-    size_t newTotalTableSize = 0;
-
-    FileNamesTable* newTable = NULL;
-
-    char* buf = NULL;
-
+UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2)
+{
+    unsigned newTableIdx = 0;
+    size_t pos = 0;
+    size_t newTotalTableSize;
+    char* buf;
 
-    newTable = UTIL_createFileNamesTable(NULL, NULL, 0);
+    fprintf(stderr, "UTIL_concatenateTwoTables \n");
 
-    if(!newTable) {
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n");
-      return NULL;
-    }
+    FileNamesTable* const newTable = UTIL_createFileNamesTable(NULL, 0, NULL);
+    CONTROL( newTable != NULL );
 
     newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2);
 
-    buf = (char*) malloc(newTotalTableSize * sizeof(char));
-    if(!buf) {
-      UTIL_freeFileNamesTable(newTable);
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create buf for concatenation output.\n");
-      return NULL;
-    }
-
-    for(i = 0; i < newTotalTableSize ; ++i) buf[i] = '\0';
+    buf = (char*) calloc(newTotalTableSize, sizeof(*buf));
+    CONTROL ( buf != NULL );
 
+    newTable->buf = buf;
+    fprintf(stderr, "Size table1 = %u ,  table2 = %u \n", (unsigned)table1->tableSize, (unsigned)table2->tableSize);
     newTable->tableSize = table1->tableSize + table2->tableSize;
-    newTable->fileNames = (const char **) malloc(newTable->tableSize * sizeof(char*));
-
-    if(!newTable->fileNames) {
-      UTIL_freeFileNamesTable(newTable);
-      if(buf) free(buf);
-      UTIL_DISPLAYLEVEL(1, "[ERROR][UTIL_concatenateTwoTables] Can't create new table for concatenation output.\n");
-      return NULL;
-    }
-
-    for (i = 0; i < newTable->tableSize; ++i)
-      newTable->fileNames[i] = NULL;
-
-    for( ; idx1 < table1->tableSize && table1->fileNames[idx1] && pos < newTotalTableSize; ++idx1, ++newTableIdx) {
-      size_t curLen = strlen(table1->fileNames[idx1]);
-      memcpy(buf+pos, table1->fileNames[idx1], curLen);
-      newTable->fileNames[newTableIdx] = buf+pos;
-      pos += curLen+1;
-    }
-
-
-    for( ; idx2 < table2->tableSize && table2->fileNames[idx2] && pos < newTotalTableSize ; ++idx2, ++newTableIdx) {
-      size_t curLen = strlen(table2->fileNames[idx2]);
-      memcpy(buf+pos, table2->fileNames[idx2], curLen);
-      newTable->fileNames[newTableIdx] = buf+pos;
-      pos += curLen+1;
-    }
-
-    if(pos > newTotalTableSize) {
-      UTIL_freeFileNamesTable(newTable);
-      if(buf) free(buf);
-      return NULL;
-    }
+    newTable->fileNames = (const char **) calloc(newTable->tableSize, sizeof(*(newTable->fileNames)));
+    CONTROL ( newTable->fileNames != NULL );
+
+    {   unsigned idx1;
+        for( idx1=0 ; (idx1 < table1->tableSize) && table1->fileNames[idx1] && (pos < newTotalTableSize); ++idx1, ++newTableIdx) {
+            size_t const curLen = strlen(table1->fileNames[idx1]);
+            memcpy(buf+pos, table1->fileNames[idx1], curLen);
+            assert(newTableIdx <= newTable->tableSize);
+            newTable->fileNames[newTableIdx] = buf+pos;
+            pos += curLen+1;
+    }   }
 
-    newTable->buf = buf;
+    {   unsigned idx2;
+        for( idx2=0 ; (idx2 < table2->tableSize) && table2->fileNames[idx2] && (pos < newTotalTableSize) ; ++idx2, ++newTableIdx) {
+            size_t const curLen = strlen(table2->fileNames[idx2]);
+            memcpy(buf+pos, table2->fileNames[idx2], curLen);
+            assert(newTableIdx <= newTable->tableSize);
+            newTable->fileNames[newTableIdx] = buf+pos;
+            pos += curLen+1;
+    }   }
+    assert(pos <= newTotalTableSize);
+    fprintf(stderr, "newTableIdx = %u ,  newTable->tableSize = %u \n", newTableIdx, (unsigned)newTable->tableSize);
+    newTable->tableSize = newTableIdx;
 
     UTIL_freeFileNamesTable(table1);
     UTIL_freeFileNamesTable(table2);
@@ -410,14 +390,17 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) {
 }
 
 #ifdef _WIN32
-int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
+int UTIL_prepareFileList(const char* dirName,
+                         char** bufStart, size_t* pos,
+                         char** bufEnd, int followLinks)
 {
     char* path;
-    int dirLength, fnameLength, pathLength, nbFiles = 0;
+    size_t dirLength;
+    int pathLength, nbFiles = 0;
     WIN32_FIND_DATAA cFile;
     HANDLE hFile;
 
-    dirLength = (int)strlen(dirName);
+    dirLength = strlen(dirName);
     path = (char*) malloc(dirLength + 3);
     if (!path) return 0;
 
@@ -434,7 +417,7 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char
     free(path);
 
     do {
-        fnameLength = (int)strlen(cFile.cFileName);
+        size_t const fnameLength = strlen(cFile.cFileName);
         path = (char*) malloc(dirLength + fnameLength + 2);
         if (!path) { FindClose(hFile); return 0; }
         memcpy(path, dirName, dirLength);
@@ -462,8 +445,7 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char
                 memcpy(*bufStart + *pos, path, pathLength+1 /* include final \0 */);
                 *pos += pathLength + 1;
                 nbFiles++;
-            }
-        }
+        }   }
         free(path);
     } while (FindNextFileA(hFile, &cFile));
 
@@ -473,12 +455,13 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char
 
 #elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */
 
-int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
+int UTIL_prepareFileList(const char *dirName,
+                         char** bufStart, size_t* pos,
+                         char** bufEnd, int followLinks)
 {
-    DIR *dir;
-    struct dirent *entry;
-    char* path;
-    size_t dirLength, fnameLength, pathLength;
+    DIR* dir;
+    struct dirent * entry;
+    size_t dirLength;
     int nbFiles = 0;
 
     if (!(dir = opendir(dirName))) {
@@ -489,6 +472,8 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char
     dirLength = strlen(dirName);
     errno = 0;
     while ((entry = readdir(dir)) != NULL) {
+        char* path;
+        size_t fnameLength, pathLength;
         if (strcmp (entry->d_name, "..") == 0 ||
             strcmp (entry->d_name, ".") == 0) continue;
         fnameLength = strlen(entry->d_name);
@@ -522,8 +507,7 @@ int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char
                 memcpy(*bufStart + *pos, path, pathLength + 1);  /* with final \0 */
                 *pos += pathLength + 1;
                 nbFiles++;
-            }
-        }
+        }   }
         free(path);
         errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
     }
@@ -605,11 +589,6 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
 }
 
 
-/*-****************************************
-*  Console log
-******************************************/
-int g_utilDisplayLevel;
-
 
 
 /*-****************************************
diff --git a/programs/util.h b/programs/util.h
index c5f42324b33..babb2644bf7 100644
--- a/programs/util.h
+++ b/programs/util.h
@@ -142,12 +142,6 @@ U32 UTIL_isLink(const char* infilename);
 U64 UTIL_getFileSize(const char* infilename);
 
 U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles);
-/*! UTIL_readLineFromFile(char* buf, size_t len, File* file):
- * @return : int. size next line in file or -1 in case of file ends
- * function reads next line in the file
- * Will also modify `*file`, advancing it to position where it stopped reading.
- */
-int UTIL_readLineFromFile(char* buf, size_t len, FILE* file);
 
 /*Note: tableSize is denotes the total capacity of table*/
 typedef struct
@@ -171,7 +165,7 @@ FileNamesTable* UTIL_createFileNamesTable_fromFileName(const char* inputFileName
  */
 
 FileNamesTable*
-UTIL_createFileNamesTable(const char** filenames, char* buf, size_t tableSize);
+UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf);
 
 
 /*!  UTIL_freeFileNamesTable(FileNamesTable* table) :
diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index e99600706cc..a7fb81eaece 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -38,8 +38,7 @@
 #ifndef ZSTD_NODICT
 #  include "dibio.h"  /* ZDICT_cover_params_t, DiB_trainFromFiles() */
 #endif
-#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_minCLevel */
-#include "zstd.h"     /* ZSTD_VERSION_STRING, ZSTD_maxCLevel */
+#include "zstd.h"     /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */
 
 
 /*-************************************
@@ -587,9 +586,6 @@ int main(int argCount, const char* argv[])
     unsigned memLimit = 0;
     size_t filenameTableSize = argCount;
     const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*));   /* argCount >= 1 */
-    FileNamesTable* extendedTable = NULL;
-    FileNamesTable* concatenatedTables = NULL;
-    FileNamesTable* curTable = NULL;
     char* tableBuf = NULL;
     unsigned filenameIdx = 0;
     const char* programName = argv[0];
@@ -804,40 +800,49 @@ int main(int argCount, const char* argv[])
 #endif
 
                     if (longCommandWArg(&argument, "--file=")) {
+                        FileNamesTable* extendedTable;
+                        FileNamesTable* curTable;
+                        FileNamesTable* concatenatedTables;
 
-                        if(!UTIL_fileExist(argument) || !UTIL_isRegularFile(argument)){
-                          DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument);
-                          CLEAN_RETURN(badusage(programName));
+                        if (!UTIL_fileExist(argument) || !UTIL_isRegularFile(argument)){
+                            DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument);
+                            CLEAN_RETURN(badusage(programName));
                         }
 
                         extendedTable = UTIL_createFileNamesTable_fromFileName(argument);
-                        if(!extendedTable) {
-                          CLEAN_RETURN(badusage(programName));
+                        if (!extendedTable) {
+                            CLEAN_RETURN(badusage(programName));
                         }
 
 
                         filenameTable[filenameIdx] = NULL; // marking end of table
+                        filenameIdx += (unsigned) extendedTable->tableSize;
 
-                        curTable = UTIL_createFileNamesTable(filenameTable, tableBuf, filenameTableSize);
+                        curTable = UTIL_createFileNamesTable(filenameTable, filenameTableSize, tableBuf);
 
-                        if(!curTable) {
-                          UTIL_freeFileNamesTable(extendedTable);
-                          CLEAN_RETURN(badusage(programName));
+                        if (!curTable) {
+                            UTIL_freeFileNamesTable(extendedTable);
+                            CLEAN_RETURN(badusage(programName));
                         }
 
                         concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable);
-                        if(!concatenatedTables) {
-                          UTIL_freeFileNamesTable(curTable);
-                          UTIL_freeFileNamesTable(extendedTable);
-                          CLEAN_RETURN(badusage(programName));
+                        if (!concatenatedTables) {
+                            if (!isTableBufferBased) curTable->buf = NULL;
+                            UTIL_freeFileNamesTable(curTable);
+                            UTIL_freeFileNamesTable(extendedTable);
+                            CLEAN_RETURN(badusage(programName));
                         }
 
+                        /* transfer ownership */
                         filenameTable = concatenatedTables->fileNames;
                         filenameTableSize = concatenatedTables->tableSize;
                         tableBuf = concatenatedTables->buf;
+                        concatenatedTables->fileNames = NULL;
+                        concatenatedTables->tableSize = 0;
+                        concatenatedTables->buf = NULL;
+                        UTIL_freeFileNamesTable(concatenatedTables);
 
-                        filenameIdx += (unsigned) extendedTable->tableSize;
-                        isTableBufferBased = 1;
+                        isTableBufferBased = 1;   /* file names are now in heap */
 
                         continue;
                     }
@@ -1106,7 +1111,7 @@ int main(int argCount, const char* argv[])
         if (cLevelLast < cLevel) cLevelLast = cLevel;
         if (cLevelLast > cLevel)
             DISPLAYLEVEL(3, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
-        if(filenameIdx) {
+        if (filenameIdx) {
             if(separateFiles) {
                 unsigned i;
                 for(i = 0; i < filenameIdx; i++) {
@@ -1114,18 +1119,15 @@ int main(int argCount, const char* argv[])
                     DISPLAYLEVEL(3, "Benchmarking %s \n", filenameTable[i]);
                     for(c = cLevel; c <= cLevelLast; c++) {
                         BMK_benchFilesAdvanced(&filenameTable[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams);
-                    }
-                }
+                }   }
             } else {
                 for(; cLevel <= cLevelLast; cLevel++) {
                     BMK_benchFilesAdvanced(filenameTable, filenameIdx, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams);
-                }
-            }
+            }   }
         } else {
             for(; cLevel <= cLevelLast; cLevel++) {
                 BMK_syntheticTest(cLevel, compressibility, &compressionParams, g_displayLevel, &benchParams);
-            }
-        }
+        }   }
 
 #else
         (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility;
@@ -1238,10 +1240,11 @@ int main(int argCount, const char* argv[])
             }
         }
         FIO_setMemLimit(prefs, memLimit);
-        if (filenameIdx==1 && outFileName)
+        if (filenameIdx==1 && outFileName) {
             operationResult = FIO_decompressFilename(prefs, outFileName, filenameTable[0], dictFileName);
-        else
+        } else {
             operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outDirName, outFileName, dictFileName);
+        }
 #else
         DISPLAY("Decompression not supported \n");
 #endif
@@ -1255,9 +1258,6 @@ int main(int argCount, const char* argv[])
          free(tableBuf);
        }
     }
-    UTIL_freeFileNamesTable(curTable);
-    UTIL_freeFileNamesTable(extendedTable);
-    UTIL_freeFileNamesTable(concatenatedTables);
 
     if (main_pause) waitEnter();
 #ifdef UTIL_HAS_CREATEFILELIST
diff --git a/tests/playTests.sh b/tests/playTests.sh
index 4e71c678d45..6ba542f4d65 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -293,49 +293,45 @@ test -f tmpOutDirDecomp/tmp2
 test -f tmpOutDirDecomp/tmp1
 rm -rf tmp*
 
+
 println "test : compress multiple files reading them from a file, --file=FILE"
-mkdir tmpInputTestDir
-println "Hello world!, file1" > tmpInputTestDir/file1
-println "Hello world!, file2" > tmpInputTestDir/file2
-println tmpInputTestDir/file1 > tmp
-println tmpInputTestDir/file2 >> tmp
-$ZSTD -f --file=tmp
-test -f tmpInputTestDir/file2.zst
-test -f tmpInputTestDir/file1.zst
-rm tmpInputTestDir/*.zst
+println "Hello world!, file1" > tmp1
+println "Hello world!, file2" > tmp2
+println tmp1 > tmp_fileList
+println tmp2 >> tmp_fileList
+$ZSTD -f --file=tmp_fileList
+test -f tmp2.zst
+test -f tmp1.zst
+rm -f *.zst
 
 println "test : compress multiple files reading them from multiple files, --file=FILE"
-println "Hello world!, file3" > tmpInputTestDir/file3
-println "Hello world!, file4" > tmpInputTestDir/file4
-println tmpInputTestDir/file3 > tmp1
-println tmpInputTestDir/file4 >> tmp1
-$ZSTD -f --file=tmp --file=tmp1
-test -f tmpInputTestDir/file1.zst
-test -f tmpInputTestDir/file2.zst
-test -f tmpInputTestDir/file3.zst
-test -f tmpInputTestDir/file4.zst
+println "Hello world!, file3" > tmp3
+println "Hello world!, file4" > tmp4
+println tmp3 > tmp_fileList2
+println tmp4 >> tmp_fileList2
+$ZSTD -f --file=tmp_fileList --file=tmp_fileList2
+test -f tmp1.zst
+test -f tmp2.zst
+test -f tmp3.zst
+test -f tmp4.zst
 
 println "test : decompress multiple files reading them from a file, --file=FILE"
-rm tmpInputTestDir/file1
-rm tmpInputTestDir/file2
-println tmpInputTestDir/file1.zst > tmpZst
-println tmpInputTestDir/file2.zst >> tmpZst
+rm -f tmp1 tmp2
+println tmp1.zst > tmpZst
+println tmp2.zst >> tmpZst
 $ZSTD -d -f --file=tmpZst
-test -f tmpInputTestDir/file2
-test -f tmpInputTestDir/file1
+test -f tmp1
+test -f tmp2
 
 println "test : decompress multiple files reading them from multiple files, --file=FILE"
-rm tmpInputTestDir/file1
-rm tmpInputTestDir/file2
-rm tmpInputTestDir/file3
-rm tmpInputTestDir/file4
-println tmpInputTestDir/file3.zst > tmpZst1
-println tmpInputTestDir/file4.zst >> tmpZst1
-$ZSTD -d -f --file=tmpZst --file=tmpZst1
-test -f tmpInputTestDir/file1
-test -f tmpInputTestDir/file2
-test -f tmpInputTestDir/file3
-test -f tmpInputTestDir/file4
+rm -f tmp1 tmp2 tmp3 tmp4
+println tmp3.zst > tmpZst2
+println tmp4.zst >> tmpZst2
+$ZSTD -d -f --file=tmpZst --file=tmpZst2
+test -f tmp1
+test -f tmp2
+test -f tmp3
+test -f tmp4
 
 rm -rf tmp*
 

From 8e414b586d1a8626a712a9ceffa21b9e6ee4a5ab Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Fri, 25 Oct 2019 17:01:26 -0700
Subject: [PATCH 020/402] test resilience on garbage file

and clean traces
---
 programs/util.c    | 9 ---------
 tests/playTests.sh | 8 ++++++++
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index 57602d1a239..e2115301c52 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -219,10 +219,8 @@ U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbF
  *           or 0, if there is no new line */
 static size_t readLineFromFile(char* buf, size_t len, FILE* file)
 {
-    fprintf(stderr, "readLineFromFile \n");
     assert(!feof(file));
     CONTROL( fgets(buf, (int) len, file) == buf );  /* requires success */
-    fprintf(stderr, "line = %s \n", buf);
     if (strlen(buf)==0) return 0;
     return strlen(buf) - (buf[strlen(buf)-1] == '\n');   /* -1 to ignore final '\n' character */
 }
@@ -244,8 +242,6 @@ readLinesFromFile(void* dst, size_t dstCapacity,
 
     assert(dst != NULL);
 
-    fprintf(stderr, "readLinesFromFile %s \n", inputFileName);
-
     if(!inputFile) {
         if (g_utilDisplayLevel >= 1) perror("zstd:util:readLinesFromFile");
         return -1;
@@ -258,7 +254,6 @@ readLinesFromFile(void* dst, size_t dstCapacity,
         buf[pos+lineLength] = '\0'; /* replace '\n' with '\0'*/
         pos += lineLength + 1;
         ++nbFiles;
-        fprintf(stderr, "nbFiles = %i \n", nbFiles);
     }
 
     CONTROL( fclose(inputFile) == 0 );
@@ -346,8 +341,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2)
     size_t newTotalTableSize;
     char* buf;
 
-    fprintf(stderr, "UTIL_concatenateTwoTables \n");
-
     FileNamesTable* const newTable = UTIL_createFileNamesTable(NULL, 0, NULL);
     CONTROL( newTable != NULL );
 
@@ -357,7 +350,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2)
     CONTROL ( buf != NULL );
 
     newTable->buf = buf;
-    fprintf(stderr, "Size table1 = %u ,  table2 = %u \n", (unsigned)table1->tableSize, (unsigned)table2->tableSize);
     newTable->tableSize = table1->tableSize + table2->tableSize;
     newTable->fileNames = (const char **) calloc(newTable->tableSize, sizeof(*(newTable->fileNames)));
     CONTROL ( newTable->fileNames != NULL );
@@ -380,7 +372,6 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2)
             pos += curLen+1;
     }   }
     assert(pos <= newTotalTableSize);
-    fprintf(stderr, "newTableIdx = %u ,  newTable->tableSize = %u \n", newTableIdx, (unsigned)newTable->tableSize);
     newTable->tableSize = newTableIdx;
 
     UTIL_freeFileNamesTable(table1);
diff --git a/tests/playTests.sh b/tests/playTests.sh
index 6ba542f4d65..8adf97df783 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -333,6 +333,14 @@ test -f tmp2
 test -f tmp3
 test -f tmp4
 
+println "test : survive a list of files which is text garbage (--file=FILE)"
+./datagen > tmp_badList
+$ZSTD -f --file=tmp_badList && die "should have failed : list is text garbage"
+
+println "test : survive a list of files which is binary garbage (--file=FILE)"
+./datagen -P0 -g1M > tmp_badList
+$ZSTD -qq -f --file=tmp_badList && die "should have failed : list is binary garbage"  # let's avoid printing binary garbage on console
+
 rm -rf tmp*
 
 

From 5fb84ca2cf35256778f982b2612b2067439079f2 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Fri, 25 Oct 2019 17:34:29 -0700
Subject: [PATCH 021/402] no need to track tableBuf

free() is compatible with NULL,
let's free() unconditionnally
---
 programs/util.c    |  9 ++++-----
 programs/util.h    | 34 +++++++++++++++++-----------------
 programs/zstdcli.c | 10 +---------
 3 files changed, 22 insertions(+), 31 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index e2115301c52..41015d2bcd9 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -200,17 +200,16 @@ U64 UTIL_getFileSize(const char* infilename)
 }
 
 
-U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles)
+U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles)
 {
     U64 total = 0;
-    int error = 0;
     unsigned n;
     for (n=0; nbuf = NULL;
                             UTIL_freeFileNamesTable(curTable);
                             UTIL_freeFileNamesTable(extendedTable);
                             CLEAN_RETURN(badusage(programName));
@@ -842,8 +840,6 @@ int main(int argCount, const char* argv[])
                         concatenatedTables->buf = NULL;
                         UTIL_freeFileNamesTable(concatenatedTables);
 
-                        isTableBufferBased = 1;   /* file names are now in heap */
-
                         continue;
                     }
                     /* fall-through, will trigger bad_usage() later on */
@@ -1253,11 +1249,7 @@ int main(int argCount, const char* argv[])
 _end:
     FIO_freePreferences(prefs);
 
-    if(filenameTable) {
-       if(isTableBufferBased && tableBuf){
-         free(tableBuf);
-       }
-    }
+    free(tableBuf);
 
     if (main_pause) waitEnter();
 #ifdef UTIL_HAS_CREATEFILELIST

From b40eaced9410ec4f26cfeb7e5a5ea566adf2f82b Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Fri, 25 Oct 2019 18:16:45 -0700
Subject: [PATCH 022/402] minor cosmetic refactoring

---
 programs/zstdcli.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index 731b330188c..5b0f6e2189f 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -814,7 +814,7 @@ int main(int argCount, const char* argv[])
                         }
 
 
-                        filenameTable[filenameIdx] = NULL; // marking end of table
+                        filenameTable[filenameIdx] = NULL;   /* marking end of table */
                         filenameIdx += (unsigned) extendedTable->tableSize;
 
                         curTable = UTIL_createFileNamesTable(filenameTable, filenameTableSize, tableBuf);
@@ -1054,8 +1054,7 @@ int main(int argCount, const char* argv[])
                 DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", filenameTable[u]);
             } else {
                 filenameTable[fileNamesNb++] = filenameTable[u];
-            }
-        }
+        }   }
         if (fileNamesNb == 0 && filenameIdx > 0)
             CLEAN_RETURN(1);
         filenameIdx = fileNamesNb;
@@ -1068,8 +1067,7 @@ int main(int argCount, const char* argv[])
             free((void*)filenameTable);
             filenameTable = extendedFileList;
             filenameIdx = fileNamesNb;
-        }
-    }
+    }   }
 #else
     (void)followLinks;
 #endif
@@ -1257,6 +1255,7 @@ int main(int argCount, const char* argv[])
         UTIL_freeFileList(extendedFileList, fileNamesBuf);
     else
 #endif
-        free((void*)filenameTable);
+    free((void*)filenameTable);
+
     return operationResult;
 }

From 74d872e98756384ea35cfc600711fc74b2d06ebb Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Fri, 25 Oct 2019 18:26:30 -0700
Subject: [PATCH 023/402] fix minor conversion warning on 32-bit

---
 programs/util.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index 41015d2bcd9..59f7b098441 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -385,8 +385,8 @@ int UTIL_prepareFileList(const char* dirName,
                          char** bufEnd, int followLinks)
 {
     char* path;
-    size_t dirLength;
-    int pathLength, nbFiles = 0;
+    size_t dirLength, pathLength;
+    int nbFiles = 0;
     WIN32_FIND_DATAA cFile;
     HANDLE hFile;
 

From 3e5c81ea3643fcba66d91779284bf1323e46714b Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Sat, 26 Oct 2019 00:01:11 -0700
Subject: [PATCH 024/402] fixed another minor conversion warning on Visual

and made CONTROL() use exit() instead of abort().
---
 programs/util.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index 59f7b098441..29830d95636 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -36,7 +36,7 @@ extern "C" {
     if (!(c)) {               \
         UTIL_DISPLAYLEVEL(1, "Error : %s, %i : %s",  \
                           __FILE__, __LINE__, #c);   \
-        abort();              \
+        exit(1);              \
 }   }
 
 
@@ -235,7 +235,7 @@ readLinesFromFile(void* dst, size_t dstCapacity,
             const char* inputFileName)
 {
     int nbFiles = 0;
-    unsigned pos = 0;
+    size_t pos = 0;
     char* const buf = (char*)dst;
     FILE* const inputFile = fopen(inputFileName, "r");
 

From 12efa1ed89016cd01260d45c3b418b1fac0f8911 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Sat, 26 Oct 2019 00:27:32 -0700
Subject: [PATCH 025/402] yet another minor visual conversion warning

this time for 32-bit systems
---
 programs/util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/programs/util.c b/programs/util.c
index 29830d95636..6db0c85e7ba 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -275,7 +275,7 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName)
     {   U64 const inputFileSize = UTIL_getFileSize(inputFileName);
         if(inputFileSize > MAX_FILE_OF_FILE_NAMES_SIZE)
             return NULL;
-        bufSize = inputFileSize + 1; /* (+1) to add '\0' at the end of last filename */
+        bufSize = (size_t)(inputFileSize + 1); /* (+1) to add '\0' at the end of last filename */
     }
 
     buf = (char*) malloc(bufSize);

From d7f258d8459b00d1bdb7ddb1073aac74b1b4a8f7 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 28 Oct 2019 13:54:36 -0700
Subject: [PATCH 026/402] change command name to `--filelist=`

updated documentation and man page
---
 programs/zstd.1    | 145 +++++++++++++++++++--------------------------
 programs/zstd.1.md |   3 +
 programs/zstdcli.c |  11 +++-
 tests/playTests.sh |  24 ++++----
 4 files changed, 85 insertions(+), 98 deletions(-)

diff --git a/programs/zstd.1 b/programs/zstd.1
index fef0e76e081..b5b4134c043 100644
--- a/programs/zstd.1
+++ b/programs/zstd.1
@@ -95,120 +95,97 @@ Display information related to a zstd compressed file, such as size, ratio, and
 .
 .SS "Operation modifiers"
 .
-.TP
-\fB\-#\fR
-\fB#\fR compression level [1\-19] (default: 3)
+.IP "\(bu" 4
+\fB\-#\fR: \fB#\fR compression level [1\-19] (default: 3)
 .
-.TP
-\fB\-\-fast[=#]\fR
-switch to ultra\-fast compression levels\. If \fB=#\fR is not present, it defaults to \fB1\fR\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. This setting overwrites compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\.
+.IP "\(bu" 4
+\fB\-\-fast[=#]\fR: switch to ultra\-fast compression levels\. If \fB=#\fR is not present, it defaults to \fB1\fR\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. This setting overwrites compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\.
 .
-.TP
-\fB\-\-ultra\fR
-unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note that decompression will also require more memory when using these levels\.
+.IP "\(bu" 4
+\fB\-\-ultra\fR: unlocks high compression levels 20+ (maximum 22), using a lot more memory\. Note that decompression will also require more memory when using these levels\.
 .
-.TP
-\fB\-\-long[=#]\fR
-enables long distance matching with \fB#\fR \fBwindowLog\fR, if not \fB#\fR is not present it defaults to \fB27\fR\. This increases the window size (\fBwindowLog\fR) and memory usage for both the compressor and decompressor\. This setting is designed to improve the compression ratio for files with long matches at a large distance\.
+.IP "\(bu" 4
+\fB\-\-long[=#]\fR: enables long distance matching with \fB#\fR \fBwindowLog\fR, if not \fB#\fR is not present it defaults to \fB27\fR\. This increases the window size (\fBwindowLog\fR) and memory usage for both the compressor and decompressor\. This setting is designed to improve the compression ratio for files with long matches at a large distance\.
 .
 .IP
 Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\.
 .
-.TP
-\fB\-T#\fR, \fB\-\-threads=#\fR
-Compress using \fB#\fR working threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to ZSTDMT_NBTHREADS_MAX==200\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\.
+.IP "\(bu" 4
+\fB\-T#\fR, \fB\-\-threads=#\fR: Compress using \fB#\fR working threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to ZSTDMT_NBTHREADS_MAX==200\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\.
 .
-.TP
-\fB\-\-single\-thread\fR
-Does not spawn a thread for compression, use a single thread for both I/O and compression\. In this mode, compression is serialized with I/O, which is slightly slower\. (This is different from \fB\-T1\fR, which spawns 1 compression thread in parallel of I/O)\. This mode is the only one available when multithread support is disabled\. Single\-thread mode features lower memory usage\. Final compressed result is slightly different from \fB\-T1\fR\.
+.IP "\(bu" 4
+\fB\-\-single\-thread\fR: Does not spawn a thread for compression, use a single thread for both I/O and compression\. In this mode, compression is serialized with I/O, which is slightly slower\. (This is different from \fB\-T1\fR, which spawns 1 compression thread in parallel of I/O)\. This mode is the only one available when multithread support is disabled\. Single\-thread mode features lower memory usage\. Final compressed result is slightly different from \fB\-T1\fR\.
 .
-.TP
-\fB\-\-adapt[=min=#,max=#]\fR
-\fBzstd\fR will dynamically adapt compression level to perceived I/O conditions\. Compression level adaptation can be observed live by using command \fB\-v\fR\. Adaptation can be constrained between supplied \fBmin\fR and \fBmax\fR levels\. The feature works when combined with multi\-threading and \fB\-\-long\fR mode\. It does not work with \fB\-\-single\-thread\fR\. It sets window size to 8 MB by default (can be changed manually, see \fBwlog\fR)\. Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible\. \fInote\fR : at the time of this writing, \fB\-\-adapt\fR can remain stuck at low speed when combined with multiple worker threads (>=2)\.
+.IP "\(bu" 4
+\fB\-\-adapt[=min=#,max=#]\fR : \fBzstd\fR will dynamically adapt compression level to perceived I/O conditions\. Compression level adaptation can be observed live by using command \fB\-v\fR\. Adaptation can be constrained between supplied \fBmin\fR and \fBmax\fR levels\. The feature works when combined with multi\-threading and \fB\-\-long\fR mode\. It does not work with \fB\-\-single\-thread\fR\. It sets window size to 8 MB by default (can be changed manually, see \fBwlog\fR)\. Due to the chaotic nature of dynamic adaptation, compressed result is not reproducible\. \fInote\fR : at the time of this writing, \fB\-\-adapt\fR can remain stuck at low speed when combined with multiple worker threads (>=2)\.
 .
-.TP
-\fB\-\-stream\-size=#\fR
-Sets the pledged source size of input coming from a stream\. This value must be exact, as it will be included in the produced frame header\. Incorrect stream sizes will cause an error\. This information will be used to better optimize compression parameters, resulting in better and potentially faster compression, especially for smaller source sizes\.
+.IP "\(bu" 4
+\fB\-\-stream\-size=#\fR : Sets the pledged source size of input coming from a stream\. This value must be exact, as it will be included in the produced frame header\. Incorrect stream sizes will cause an error\. This information will be used to better optimize compression parameters, resulting in better and potentially faster compression, especially for smaller source sizes\.
 .
-.TP
-\fB\-\-size\-hint=#\fR
-When handling input from a stream, \fBzstd\fR must guess how large the source size will be when optimizing compression parameters\. If the stream size is relatively small, this guess may be a poor one, resulting in a higher compression ratio than expected\. This feature allows for controlling the guess when needed\. Exact guesses result in better compression ratios\. Overestimates result in slightly degraded compression ratios, while underestimates may result in significant degradation\.
+.IP "\(bu" 4
+\fB\-\-size\-hint=#\fR: When handling input from a stream, \fBzstd\fR must guess how large the source size will be when optimizing compression parameters\. If the stream size is relatively small, this guess may be a poor one, resulting in a higher compression ratio than expected\. This feature allows for controlling the guess when needed\. Exact guesses result in better compression ratios\. Overestimates result in slightly degraded compression ratios, while underestimates may result in significant degradation\.
 .
-.TP
-\fB\-\-rsyncable\fR
-\fBzstd\fR will periodically synchronize the compression state to make the compressed file more rsync\-friendly\. There is a negligible impact to compression ratio, and the faster compression levels will see a small compression speed hit\. This feature does not work with \fB\-\-single\-thread\fR\. You probably don\'t want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your milage may vary\.
+.IP "\(bu" 4
+\fB\-\-rsyncable\fR : \fBzstd\fR will periodically synchronize the compression state to make the compressed file more rsync\-friendly\. There is a negligible impact to compression ratio, and the faster compression levels will see a small compression speed hit\. This feature does not work with \fB\-\-single\-thread\fR\. You probably don\'t want to use it with long range mode, since it will decrease the effectiveness of the synchronization points, but your milage may vary\.
 .
-.TP
-\fB\-D file\fR
-use \fBfile\fR as Dictionary to compress or decompress FILE(s)
+.IP "\(bu" 4
+\fB\-D file\fR: use \fBfile\fR as Dictionary to compress or decompress FILE(s)
 .
-.TP
-\fB\-\-no\-dictID\fR
-do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\'t be able to check if it\'s correct\.
+.IP "\(bu" 4
+\fB\-\-no\-dictID\fR: do not store dictionary ID within frame header (dictionary compression)\. The decoder will have to rely on implicit knowledge about which dictionary to use, it won\'t be able to check if it\'s correct\.
 .
-.TP
-\fB\-o file\fR
-save result into \fBfile\fR (only possible with a single \fIINPUT\-FILE\fR)
+.IP "\(bu" 4
+\fB\-o file\fR: save result into \fBfile\fR (only possible with a single \fIINPUT\-FILE\fR)
 .
-.TP
-\fB\-f\fR, \fB\-\-force\fR
-overwrite output without prompting, and (de)compress symbolic links
+.IP "\(bu" 4
+\fB\-f\fR, \fB\-\-force\fR: overwrite output without prompting, and (de)compress symbolic links
 .
-.TP
-\fB\-c\fR, \fB\-\-stdout\fR
-force write to standard output, even if it is the console
+.IP "\(bu" 4
+\fB\-c\fR, \fB\-\-stdout\fR: force write to standard output, even if it is the console
 .
-.TP
-\fB\-\-[no\-]sparse\fR
-enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default: enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\.
+.IP "\(bu" 4
+\fB\-\-[no\-]sparse\fR: enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default: enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\.
 .
-.TP
-\fB\-\-rm\fR
-remove source file(s) after successful compression or decompression
+.IP "\(bu" 4
+\fB\-\-rm\fR: remove source file(s) after successful compression or decompression
 .
-.TP
-\fB\-k\fR, \fB\-\-keep\fR
-keep source file(s) after successful compression or decompression\. This is the default behavior\.
+.IP "\(bu" 4
+\fB\-k\fR, \fB\-\-keep\fR: keep source file(s) after successful compression or decompression\. This is the default behavior\.
 .
-.TP
-\fB\-r\fR
-operate recursively on directories
+.IP "\(bu" 4
+\fB\-r\fR: operate recursively on directories
 .
-.TP
-\fB\-\-output\-dir\-flat[=dir]\fR
-resulting files are stored into target \fBdir\fR directory, instead of same directory as origin file\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\. Collision resolution ensures first file with a given name will be present in \fBdir\fR, while in combination with \fB\-f\fR, the last file will be present instead\.
+.IP "\(bu" 4
+\fB\-\-filelist=FILE\fR read a list of files to process as content from \fBFILE\fR\. Format is compatible with \fBls\fR output, with one file per file\.
 .
-.TP
-\fB\-\-format=FORMAT\fR
-compress and decompress in other formats\. If compiled with support, zstd can compress to or decompress from other compression algorithm formats\. Possibly available options are \fBzstd\fR, \fBgzip\fR, \fBxz\fR, \fBlzma\fR, and \fBlz4\fR\. If no such format is provided, \fBzstd\fR is the default\.
+.IP "\(bu" 4
+\fB\-\-output\-dir\-flat[=dir]\fR: resulting files are stored into target \fBdir\fR directory, instead of same directory as origin file\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\. Collision resolution ensures first file with a given name will be present in \fBdir\fR, while in combination with \fB\-f\fR, the last file will be present instead\.
 .
-.TP
-\fB\-h\fR/\fB\-H\fR, \fB\-\-help\fR
-display help/long help and exit
+.IP "\(bu" 4
+\fB\-\-format=FORMAT\fR: compress and decompress in other formats\. If compiled with support, zstd can compress to or decompress from other compression algorithm formats\. Possibly available options are \fBzstd\fR, \fBgzip\fR, \fBxz\fR, \fBlzma\fR, and \fBlz4\fR\. If no such format is provided, \fBzstd\fR is the default\.
 .
-.TP
-\fB\-V\fR, \fB\-\-version\fR
-display version number and exit\. Advanced : \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\.
+.IP "\(bu" 4
+\fB\-h\fR/\fB\-H\fR, \fB\-\-help\fR: display help/long help and exit
 .
-.TP
-\fB\-v\fR
-verbose mode
+.IP "\(bu" 4
+\fB\-V\fR, \fB\-\-version\fR: display version number and exit\. Advanced : \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\.
 .
-.TP
-\fB\-q\fR, \fB\-\-quiet\fR
-suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\.
+.IP "\(bu" 4
+\fB\-v\fR: verbose mode
 .
-.TP
-\fB\-\-no\-progress\fR
-do not display the progress bar, but keep all other messages\.
+.IP "\(bu" 4
+\fB\-q\fR, \fB\-\-quiet\fR: suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\.
 .
-.TP
-\fB\-C\fR, \fB\-\-[no\-]check\fR
-add integrity check computed from uncompressed data (default: enabled)
+.IP "\(bu" 4
+\fB\-\-no\-progress\fR: do not display the progress bar, but keep all other messages\.
 .
-.TP
-\fB\-\-\fR
-All arguments after \fB\-\-\fR are treated as files
+.IP "\(bu" 4
+\fB\-C\fR, \fB\-\-[no\-]check\fR: add integrity check computed from uncompressed data (default: enabled)
+.
+.IP "\(bu" 4
+\fB\-\-\fR: All arguments after \fB\-\-\fR are treated as files
+.
+.IP "" 0
 .
 .SS "Restricted usage of Environment Variables"
 Using environment variables to set parameters has security implications\. Therefore, this avenue is intentionally restricted\. Only \fBZSTD_CLEVEL\fR is supported currently, for setting compression level\. \fBZSTD_CLEVEL\fR can be used to set the level between 1 and 19 (the "normal" range)\. If the value of \fBZSTD_CLEVEL\fR is not a valid integer, it will be ignored with a warning message\. \fBZSTD_CLEVEL\fR just replaces the default compression level (\fB3\fR)\. It can be overridden by corresponding command line arguments\.
diff --git a/programs/zstd.1.md b/programs/zstd.1.md
index e3daa4c87ac..50dc7c8f9e4 100644
--- a/programs/zstd.1.md
+++ b/programs/zstd.1.md
@@ -191,6 +191,9 @@ the last one takes effect.
     This is the default behavior.
 * `-r`:
     operate recursively on directories
+* `--filelist=FILE`
+    read a list of files to process as content from `FILE`.
+    Format is compatible with `ls` output, with one file per file.
 * `--output-dir-flat[=dir]`:
     resulting files are stored into target `dir` directory,
     instead of same directory as origin file.
diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index 5b0f6e2189f..831143f10d5 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -154,7 +154,8 @@ static int usage_advanced(const char* programName)
 #endif
 #ifdef UTIL_HAS_CREATEFILELIST
     DISPLAY( " -r     : operate recursively on directories \n");
-    DISPLAY( "--output-dir-flat[=directory]: all resulting files stored into `directory`. \n");
+    DISPLAY( "--filelist=FILE : read a list of files from FILE. \n");
+    DISPLAY( "--output-dir-flat=DIR : all resulting files are stored into DIR. \n");
 #endif
     DISPLAY( "--format=zstd : compress files to the .zst format (default) \n");
 #ifdef ZSTD_GZCOMPRESS
@@ -798,7 +799,13 @@ int main(int argCount, const char* argv[])
                     }
 #endif
 
-                    if (longCommandWArg(&argument, "--file=")) {
+                    if (longCommandWArg(&argument, "--filelist=")) {
+                        /* note : in theory, it's better to just store the arguments at this stage,
+                         *    and only start to load & interpret the file after command line is parsed.
+                         *    For a single file, it would be easy to just store its name here, and parse later.
+                         *    However, this implementation makes it possible to read multiple files.
+                         *    An equivalent will have to be able to store multiple file names.
+                         */
                         FileNamesTable* extendedTable;
                         FileNamesTable* curTable;
                         FileNamesTable* concatenatedTables;
diff --git a/tests/playTests.sh b/tests/playTests.sh
index cd4d50459a3..d730c0c5dd8 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -294,52 +294,52 @@ test -f tmpOutDirDecomp/tmp1
 rm -rf tmp*
 
 
-println "test : compress multiple files reading them from a file, --file=FILE"
+println "test : compress multiple files reading them from a file, --filelist=FILE"
 println "Hello world!, file1" > tmp1
 println "Hello world!, file2" > tmp2
 println tmp1 > tmp_fileList
 println tmp2 >> tmp_fileList
-$ZSTD -f --file=tmp_fileList
+$ZSTD -f --filelist=tmp_fileList
 test -f tmp2.zst
 test -f tmp1.zst
 rm -f *.zst
 
-println "test : compress multiple files reading them from multiple files, --file=FILE"
+println "test : compress multiple files reading them from multiple files, --filelist=FILE"
 println "Hello world!, file3" > tmp3
 println "Hello world!, file4" > tmp4
 println tmp3 > tmp_fileList2
 println tmp4 >> tmp_fileList2
-$ZSTD -f --file=tmp_fileList --file=tmp_fileList2
+$ZSTD -f --filelist=tmp_fileList --filelist=tmp_fileList2
 test -f tmp1.zst
 test -f tmp2.zst
 test -f tmp3.zst
 test -f tmp4.zst
 
-println "test : decompress multiple files reading them from a file, --file=FILE"
+println "test : decompress multiple files reading them from a file, --filelist=FILE"
 rm -f tmp1 tmp2
 println tmp1.zst > tmpZst
 println tmp2.zst >> tmpZst
-$ZSTD -d -f --file=tmpZst
+$ZSTD -d -f --filelist=tmpZst
 test -f tmp1
 test -f tmp2
 
-println "test : decompress multiple files reading them from multiple files, --file=FILE"
+println "test : decompress multiple files reading them from multiple files, --filelist=FILE"
 rm -f tmp1 tmp2 tmp3 tmp4
 println tmp3.zst > tmpZst2
 println tmp4.zst >> tmpZst2
-$ZSTD -d -f --file=tmpZst --file=tmpZst2
+$ZSTD -d -f --filelist=tmpZst --filelist=tmpZst2
 test -f tmp1
 test -f tmp2
 test -f tmp3
 test -f tmp4
 
-println "test : survive a list of files which is text garbage (--file=FILE)"
+println "test : survive a list of files which is text garbage (--filelist=FILE)"
 ./datagen > tmp_badList
-$ZSTD -f --file=tmp_badList && die "should have failed : list is text garbage"
+$ZSTD -f --filelist=tmp_badList && die "should have failed : list is text garbage"
 
-println "test : survive a list of files which is binary garbage (--file=FILE)"
+println "test : survive a list of files which is binary garbage (--filelist=FILE)"
 ./datagen -P0 -g1M > tmp_badList
-$ZSTD -qq -f --file=tmp_badList && die "should have failed : list is binary garbage"  # let's avoid printing binary garbage on console
+$ZSTD -qq -f --filelist=tmp_badList && die "should have failed : list is binary garbage"  # let's avoid printing binary garbage on console
 
 rm -rf tmp*
 

From d9c634e13b4d1c0c2289a53317532bfeb989ecb4 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 28 Oct 2019 15:03:32 -0700
Subject: [PATCH 027/402] return final `\0` directly from readLine()

---
 programs/util.c    | 13 ++++++++-----
 tests/playTests.sh |  8 ++++----
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index 6db0c85e7ba..c09461ef77f 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -214,14 +214,18 @@ U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles)
 
 
 /* condition : @file must be valid, and not have reached its end.
- * @return : length of line written into buf, without the final '\n',
+ * @return : length of line written into @buf, ended with `\0` instead of '\n',
  *           or 0, if there is no new line */
 static size_t readLineFromFile(char* buf, size_t len, FILE* file)
 {
     assert(!feof(file));
     CONTROL( fgets(buf, (int) len, file) == buf );  /* requires success */
-    if (strlen(buf)==0) return 0;
-    return strlen(buf) - (buf[strlen(buf)-1] == '\n');   /* ignore final '\n' character */
+    {   size_t linelen = strlen(buf);
+        if (strlen(buf)==0) return 0;
+        if (buf[linelen-1] == '\n') linelen--;
+        buf[linelen] = '\0';
+        return linelen+1;
+    }
 }
 
 /* Conditions :
@@ -250,8 +254,7 @@ readLinesFromFile(void* dst, size_t dstCapacity,
         size_t const lineLength = readLineFromFile(buf+pos, dstCapacity-pos, inputFile);
         if (lineLength == 0) break;
         assert(pos + lineLength < dstCapacity);
-        buf[pos+lineLength] = '\0'; /* replace '\n' with '\0'*/
-        pos += lineLength + 1;
+        pos += lineLength;
         ++nbFiles;
     }
 
diff --git a/tests/playTests.sh b/tests/playTests.sh
index d730c0c5dd8..adcc1d77fc1 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -866,9 +866,8 @@ else
 fi
 
 
-println "\n===>  lz4 frame tests "
-
 if [ $LZ4MODE -eq 1 ]; then
+    println "\n===>  lz4 frame tests "
     ./datagen > tmp
     $ZSTD -f --format=lz4 tmp
     $ZSTD -f tmp
@@ -876,9 +875,10 @@ if [ $LZ4MODE -eq 1 ]; then
     truncateLastByte tmp.lz4 | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !"
     rm tmp*
 else
-    println "lz4 mode not supported"
+    println "\nlz4 mode not supported"
 fi
 
+
 println "\n===> suffix list test"
 
 ! $ZSTD -d tmp.abc 2> tmplg
@@ -896,6 +896,7 @@ if [ $LZ4MODE -ne 1 ]; then
     grep ".lz4" tmplg > $INTOVOID && die "Unsupported suffix listed"
 fi
 
+
 println "\n===>  tar extension tests "
 
 rm -f tmp tmp.tar tmp.tzst tmp.tgz tmp.txz tmp.tlz4
@@ -934,7 +935,6 @@ touch tmp.t tmp.tz tmp.tzs
 ! $ZSTD -d tmp.tz
 ! $ZSTD -d tmp.tzs
 
-exit
 
 println "\n===>  zstd round-trip tests "
 

From 170982fbd943033de6d7e74851959d6c243522ea Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 28 Oct 2019 15:15:26 -0700
Subject: [PATCH 028/402] added symlink test for --filelist=FILE

---
 tests/playTests.sh | 59 ++++++++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 23 deletions(-)

diff --git a/tests/playTests.sh b/tests/playTests.sh
index adcc1d77fc1..7712b68aa54 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -242,12 +242,14 @@ $ZSTD -f tmp && die "attempt to compress a non existing file"
 test -f tmp.zst  # destination file should still be present
 rm -rf tmp*  # may also erase tmp* directory from previous failed run
 
+
 println "\n===> decompression only tests "
 head -c 1048576 /dev/zero > tmp
 $ZSTD -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst"
 $DIFF -s tmp1 tmp
 rm tmp*
 
+
 println "test : compress multiple files"
 println hello > tmp1
 println world > tmp2
@@ -268,8 +270,33 @@ $ZSTD tmp1 tmp2 -o tmpexists && die "should have refused to overwrite"
 if [ "$?" -eq 139 ]; then
   die "should not have segfaulted"
 fi
+println "\n===>  multiple files and shell completion "
+./datagen -s1        > tmp1 2> $INTOVOID
+./datagen -s2 -g100K > tmp2 2> $INTOVOID
+./datagen -s3 -g1M   > tmp3 2> $INTOVOID
+println "compress tmp* : "
+$ZSTD -f tmp*
+test -f tmp1.zst
+test -f tmp2.zst
+test -f tmp3.zst
+rm tmp1 tmp2 tmp3
+println "decompress tmp* : "
+$ZSTD -df ./*.zst
+test -f tmp1
+test -f tmp2
+test -f tmp3
+println "compress tmp* into stdout > tmpall : "
+$ZSTD -c tmp1 tmp2 tmp3 > tmpall
+test -f tmpall  # should check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)
+println "decompress tmpall* into stdout > tmpdec : "
+cp tmpall tmpall2
+$ZSTD -dc tmpall* > tmpdec
+test -f tmpdec  # should check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))
+println "compress multiple files including a missing one (notHere) : "
+$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
 rm tmp*
 
+
 println "test : compress multiple files into an output directory, --output-dir-flat"
 println henlo > tmp1
 mkdir tmpInputTestDir
@@ -302,9 +329,16 @@ println tmp2 >> tmp_fileList
 $ZSTD -f --filelist=tmp_fileList
 test -f tmp2.zst
 test -f tmp1.zst
+
+println "test : reading file list from a symlink, --filelist=FILE"
 rm -f *.zst
+ln -s tmp_fileList tmp_symLink
+$ZSTD -f --filelist=tmp_symLink
+test -f tmp2.zst
+test -f tmp1.zst
 
 println "test : compress multiple files reading them from multiple files, --filelist=FILE"
+rm -f *.zst
 println "Hello world!, file3" > tmp3
 println "Hello world!, file4" > tmp4
 println tmp3 > tmp_fileList2
@@ -464,28 +498,6 @@ $DIFF tmpSparse2M tmpSparseRegenerated
 rm tmpSparse*
 
 
-println "\n===>  multiple files tests "
-
-./datagen -s1        > tmp1 2> $INTOVOID
-./datagen -s2 -g100K > tmp2 2> $INTOVOID
-./datagen -s3 -g1M   > tmp3 2> $INTOVOID
-println "compress tmp* : "
-$ZSTD -f tmp*
-ls -ls tmp*
-rm tmp1 tmp2 tmp3
-println "decompress tmp* : "
-$ZSTD -df ./*.zst
-ls -ls tmp*
-println "compress tmp* into stdout > tmpall : "
-$ZSTD -c tmp1 tmp2 tmp3 > tmpall
-ls -ls tmp*  # check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst)
-println "decompress tmpall* into stdout > tmpdec : "
-cp tmpall tmpall2
-$ZSTD -dc tmpall* > tmpdec
-ls -ls tmp* # check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3))
-println "compress multiple files including a missing one (notHere) : "
-$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!"
-
 println "\n===>  stream-size mode"
 
 ./datagen -g11000 > tmp
@@ -710,7 +722,6 @@ $ZSTD -t tmpSplit.* && die "bad file not detected !"
 ./datagen | $ZSTD -c | $ZSTD -t
 
 
-
 println "\n===>  golden files tests "
 
 $ZSTD -t -r "$TESTDIR/golden-compression"
@@ -732,6 +743,7 @@ println "benchmark decompression only"
 $ZSTD -f tmp1
 $ZSTD -b -d -i0 tmp1.zst
 
+
 println "\n===>  zstd compatibility tests "
 
 ./datagen > tmp
@@ -739,6 +751,7 @@ rm -f tmp.zst
 $ZSTD --format=zstd -f tmp
 test -f tmp.zst
 
+
 println "\n===>  gzip compatibility tests "
 
 GZIPMODE=1

From 65f2d97f333e920550ee27b152e29943b5ac434e Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 28 Oct 2019 15:20:40 -0700
Subject: [PATCH 029/402] updated UTIL_createFileNamesTable() inline
 documentation

---
 programs/util.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/programs/util.h b/programs/util.h
index 68e80c13acf..d83dd187163 100644
--- a/programs/util.h
+++ b/programs/util.h
@@ -151,20 +151,19 @@ typedef struct
     size_t tableSize;
 } FileNamesTable;
 
-/*! UTIL_readFileNamesTableFromFile() :
- *  reads fileNamesTable from @inputFileName.
- * @return : a FileNamesTable*, or NULL in case of error (ex: file doesn't exist).
+/*! UTIL_createFileNamesTable_fromFileName() :
+ *  read filenames from @inputFileName, and store them into returned object.
+ * @return : a FileNamesTable*, or NULL in case of error (ex: @inputFileName doesn't exist).
  *  Note: inputFileSize must be less than 50MB
  */
 FileNamesTable*
 UTIL_createFileNamesTable_fromFileName(const char* inputFileName);
 
-
-/*! UTIL_freeFileNamesTable() :
- *  This function references its arguments inside the created object.
+/*! UTIL_createFileNamesTable() :
+ *  This function takes ownership of its arguments, @filenames and @buf,
+ *  and store them inside the created object.
  * @return : FileNamesTable*, or NULL, if allocation fails.
  */
-
 FileNamesTable*
 UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf);
 
@@ -204,8 +203,9 @@ int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char
 #endif /* #ifdef _WIN32 */
 
 /*
- * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
- *                       and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
+ * UTIL_createFileList() :
+ * takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
+ * and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
  * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
  * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
  */

From 85df7a4da8fca88313475a309b10ddc3ddc06dd3 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 28 Oct 2019 16:05:42 -0700
Subject: [PATCH 030/402] added test which can overflow internal list of
 filenames

---
 tests/playTests.sh | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/playTests.sh b/tests/playTests.sh
index 7712b68aa54..5f23ac555cf 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -375,6 +375,10 @@ println "test : survive a list of files which is binary garbage (--filelist=FILE
 ./datagen -P0 -g1M > tmp_badList
 $ZSTD -qq -f --filelist=tmp_badList && die "should have failed : list is binary garbage"  # let's avoid printing binary garbage on console
 
+println "test : try to overflow internal list of files (--filelist=FILE)"
+touch tmp1 tmp2 tmp3 tmp4 tmp5 tmp6
+ls tmp* > tmpList
+$ZSTD -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3  # can trigger an overflow of internal file list
 rm -rf tmp*
 
 

From 305ac2653ea6ab761f4940aa31e284b816d4b00b Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Mon, 4 Nov 2019 10:59:59 -0800
Subject: [PATCH 031/402] update table benchmark with zstd v1.4.4

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 9c5f9201307..c94c7882a48 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ on the [Silesia compression corpus].
 
 | Compressor name         | Ratio | Compression| Decompress.|
 | ---------------         | ------| -----------| ---------- |
-| **zstd 1.4.0 -1**       | 2.884 |   530 MB/s |  1360 MB/s |
+| **zstd 1.4.4 -1**       | 2.884 |   520 MB/s |  1600 MB/s |
 | zlib 1.2.11 -1          | 2.743 |   110 MB/s |   440 MB/s |
 | brotli 1.0.7 -0         | 2.701 |   430 MB/s |   470 MB/s |
 | quicklz 1.5.0 -1        | 2.238 |   600 MB/s |   800 MB/s |

From 3fb5b106da625ea55d24c35dbb0500ff439b6500 Mon Sep 17 00:00:00 2001
From: Bimba Shrestha 
Date: Tue, 5 Nov 2019 10:26:57 -0800
Subject: [PATCH 032/402] Replacing some literals with constants

---
 lib/compress/zstd_compress_literals.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c
index 6c133311821..df3f269ded6 100644
--- a/lib/compress/zstd_compress_literals.c
+++ b/lib/compress/zstd_compress_literals.c
@@ -102,11 +102,11 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
         cLitSize = singleStream ?
             HUF_compress1X_repeat(
                 ostart+lhSize, dstCapacity-lhSize, src, srcSize,
-                255, 11, entropyWorkspace, entropyWorkspaceSize,
+                HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize,
                 (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2) :
             HUF_compress4X_repeat(
                 ostart+lhSize, dstCapacity-lhSize, src, srcSize,
-                255, 11, entropyWorkspace, entropyWorkspaceSize,
+                HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize,
                 (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
         if (repeat != HUF_repeat_none) {
             /* reused the existing table */

From 7ce891870c41fa138c6056eae836638c4b87b13f Mon Sep 17 00:00:00 2001
From: Sen Huang 
Date: Tue, 5 Nov 2019 15:51:25 -0500
Subject: [PATCH 033/402] Fix merge conflicts

---
 build/VS2008/fullbench/fullbench.vcproj      |   8 +
 build/VS2008/fuzzer/fuzzer.vcproj            |   8 +
 build/VS2008/zstd/zstd.vcproj                |   8 +
 build/VS2008/zstdlib/zstdlib.vcproj          |   8 +
 build/VS2010/fullbench/fullbench.vcxproj     |   2 +
 build/VS2010/fuzzer/fuzzer.vcxproj           |   2 +
 build/VS2010/libzstd-dll/libzstd-dll.vcxproj |   2 +
 build/VS2010/libzstd/libzstd.vcxproj         |   2 +
 build/VS2010/zstd/zstd.vcxproj               |   2 +
 build/meson/lib/meson.build                  |   1 +
 lib/common/huf.h                             |   1 +
 lib/compress/huf_compress.c                  |   2 +-
 lib/compress/zstd_compress.c                 | 121 ++-
 lib/compress/zstd_compress_internal.h        |  14 +
 lib/compress/zstd_compress_sequences.c       |   6 +-
 lib/compress/zstd_compress_sequences.h       |   7 +
 lib/compress/zstd_compress_superblock.c      | 739 +++++++++++++++++++
 lib/compress/zstd_compress_superblock.h      |  41 +
 18 files changed, 949 insertions(+), 25 deletions(-)
 create mode 100644 lib/compress/zstd_compress_superblock.c
 create mode 100644 lib/compress/zstd_compress_superblock.h

diff --git a/build/VS2008/fullbench/fullbench.vcproj b/build/VS2008/fullbench/fullbench.vcproj
index 66ac8223acb..5752643f9d1 100644
--- a/build/VS2008/fullbench/fullbench.vcproj
+++ b/build/VS2008/fullbench/fullbench.vcproj
@@ -372,6 +372,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_compress_sequences.c"
 				>
 			
+			
+			
 			
@@ -514,6 +518,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_cwksp.h"
 				>
 			
+			
+			
 			
diff --git a/build/VS2008/fuzzer/fuzzer.vcproj b/build/VS2008/fuzzer/fuzzer.vcproj
index a9008a673ae..d48bc0fab48 100644
--- a/build/VS2008/fuzzer/fuzzer.vcproj
+++ b/build/VS2008/fuzzer/fuzzer.vcproj
@@ -420,6 +420,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_compress_sequences.c"
 				>
 			
+			
+			
 			
@@ -550,6 +554,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_cwksp.h"
 				>
 			
+			
+			
 			
diff --git a/build/VS2008/zstd/zstd.vcproj b/build/VS2008/zstd/zstd.vcproj
index 4d75a9d3602..ab02e615552 100644
--- a/build/VS2008/zstd/zstd.vcproj
+++ b/build/VS2008/zstd/zstd.vcproj
@@ -432,6 +432,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_compress_sequences.c"
 				>
 			
+			
+			
 			
@@ -630,6 +634,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_cwksp.h"
 				>
 			
+			
+			
 			
diff --git a/build/VS2008/zstdlib/zstdlib.vcproj b/build/VS2008/zstdlib/zstdlib.vcproj
index 100a501aea4..5eb49f9b270 100644
--- a/build/VS2008/zstdlib/zstdlib.vcproj
+++ b/build/VS2008/zstdlib/zstdlib.vcproj
@@ -404,6 +404,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_compress_sequences.c"
 				>
 			
+			
+			
 			
@@ -562,6 +566,10 @@
 				RelativePath="..\..\..\lib\compress\zstd_cwksp.h"
 				>
 			
+			
+			
 			
diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj
index 4597239bc8c..20932fa37f8 100644
--- a/build/VS2010/fullbench/fullbench.vcxproj
+++ b/build/VS2010/fullbench/fullbench.vcxproj
@@ -169,6 +169,7 @@
     
     
     
+    
     
     
     
@@ -198,6 +199,7 @@
     
     
     
+    
     
     
     
diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj
index a6f136eefc9..8427572817d 100644
--- a/build/VS2010/fuzzer/fuzzer.vcxproj
+++ b/build/VS2010/fuzzer/fuzzer.vcxproj
@@ -169,6 +169,7 @@
     
     
     
+    
     
     
     
@@ -201,6 +202,7 @@
     
     
     
+    
     
     
     
diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj
index 50c4e817acb..0957d413bf4 100644
--- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj
+++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj
@@ -33,6 +33,7 @@
     
     
     
+    
     
     
     
@@ -83,6 +84,7 @@
     
     
     
+    
     
     
     
diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj
index c4e828773f9..203429355f5 100644
--- a/build/VS2010/libzstd/libzstd.vcxproj
+++ b/build/VS2010/libzstd/libzstd.vcxproj
@@ -33,6 +33,7 @@
     
     
     
+    
     
     
     
@@ -83,6 +84,7 @@
     
     
     
+    
     
     
     
diff --git a/build/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj
index 1058d2292b5..e320d88a149 100644
--- a/build/VS2010/zstd/zstd.vcxproj
+++ b/build/VS2010/zstd/zstd.vcxproj
@@ -34,6 +34,7 @@
     
     
     
+    
     
     
     
@@ -80,6 +81,7 @@
     
     
     
+    
     
     
     
diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build
index ef669327e35..6fb3df8e9fc 100644
--- a/build/meson/lib/meson.build
+++ b/build/meson/lib/meson.build
@@ -30,6 +30,7 @@ libzstd_sources = [join_paths(zstd_rootdir, 'lib/common/entropy_common.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstd_compress.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstd_compress_literals.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstd_compress_sequences.c'),
+  join_paths(zstd_rootdir, 'lib/compress/zstd_compress_superblock.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstdmt_compress.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstd_fast.c'),
   join_paths(zstd_rootdir, 'lib/compress/zstd_double_fast.c'),
diff --git a/lib/common/huf.h b/lib/common/huf.h
index 6b572c448d9..3026c43ea03 100644
--- a/lib/common/huf.h
+++ b/lib/common/huf.h
@@ -208,6 +208,7 @@ typedef struct HUF_CElt_s HUF_CElt;   /* incomplete type */
 size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);   /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
 size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
 size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
+size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
 
 typedef enum {
    HUF_repeat_none,  /**< Cannot use the previous table */
diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c
index f074f1e0a95..0cbba2c994e 100644
--- a/lib/compress/huf_compress.c
+++ b/lib/compress/huf_compress.c
@@ -427,7 +427,7 @@ size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbo
     return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable));
 }
 
-static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
+size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
 {
     size_t nbBits = 0;
     int s;
diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 35346b92cb1..3364098404e 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -20,6 +20,7 @@
 #include "fse.h"
 #define HUF_STATIC_LINKING_ONLY
 #include "huf.h"
+#include "zstd_compress_superblock.h"
 #include "zstd_compress_internal.h"
 #include "zstd_compress_sequences.h"
 #include "zstd_compress_literals.h"
@@ -33,6 +34,13 @@
 /*-*************************************
 *  Helper functions
 ***************************************/
+/* ZSTD_compressBound()
+ * Note that the result from this function is only compatible with the "normal"
+ * full-block strategy.
+ * When there are a lot of small blocks due to frequent flush in streaming mode
+ * or targetCBlockSize, the overhead of headers can make the compressed data to
+ * be larger than the return value of ZSTD_compressBound().
+ */
 size_t ZSTD_compressBound(size_t srcSize) {
     return ZSTD_COMPRESSBOUND(srcSize);
 }
@@ -1889,16 +1897,6 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par
 
 /* See doc/zstd_compression_format.md for detailed format description */
 
-static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
-{
-    U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
-    RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
-                    dstSize_tooSmall);
-    MEM_writeLE24(dst, cBlockHeader24);
-    memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
-    return ZSTD_blockHeaderSize + srcSize;
-}
-
 void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
 {
     const seqDef* const sequences = seqStorePtr->sequencesStart;
@@ -1936,6 +1934,16 @@ static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
     }
 }
 
+/* ZSTD_useTargetCBlockSize():
+ * Returns if target compressed block size param is being used.
+ * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.
+ * Returns 1 if true, 0 otherwise. */
+static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
+{
+    DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
+    return (cctxParams->targetCBlockSize != 0);
+}
+
 /* ZSTD_compressSequences_internal():
  * actually compresses both literals and sequences */
 MEM_STATIC size_t
@@ -2435,6 +2443,70 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
     return cSize;
 }
 
+static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
+                               void* dst, size_t dstCapacity,
+                               const void* src, size_t srcSize,
+                               U32 lastBlock) {
+    size_t cSize = 0;
+    DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)",
+                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);
+
+    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
+        FORWARD_IF_ERROR(bss);
+        if (bss == ZSTDbss_compress) {
+            cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock);
+    }   }
+
+    /* Superblock compression may fail, in which case
+     * encode using ZSTD_noCompressSuperBlock writing sub blocks
+     * in uncompressed mode.
+     */
+    if (cSize == 0) {
+        cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock);
+        /* In compression, there is an assumption that a compressed block is always
+         * within the size of ZSTD_compressBound(). However, SuperBlock compression
+         * can exceed the limit due to overhead of headers from SubBlocks.
+         * This breaks in streaming mode where output buffer in compress context is
+         * allocated ZSTD_compressBound() amount of memory, which may not be big
+         * enough for SuperBlock compression.
+         * In such case, fall back to normal compression. This is possible because
+         * targetCBlockSize is best effort not a guarantee. */
+        if (cSize != ERROR(dstSize_tooSmall)) return cSize;
+        else {
+            BYTE* const ostart = (BYTE*)dst;
+            /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall,
+             * compress normally.
+             */
+            cSize = ZSTD_compressSequences(&zc->seqStore,
+                    &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
+                    &zc->appliedParams,
+                    ostart+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
+                    srcSize,
+                    zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
+                    zc->bmi2);
+            if (!ZSTD_isError(cSize) && cSize != 0) {
+                U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
+                MEM_writeLE24(ostart, cBlockHeader24);
+                cSize += ZSTD_blockHeaderSize;
+            }
+        }
+    }
+
+    if (!ZSTD_isError(cSize) && cSize != 0) {
+        /* confirm repcodes and entropy tables when emitting a compressed block */
+        ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
+        zc->blockState.prevCBlock = zc->blockState.nextCBlock;
+        zc->blockState.nextCBlock = tmp;
+    }
+    /* We check that dictionaries have offset codes available for the first
+     * block. After the first block, the offcode table might not have large
+     * enough codes to represent the offsets in the data.
+     */
+    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+
+    return cSize;
+}
 
 static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
                                          ZSTD_cwksp* ws,
@@ -2500,21 +2572,28 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
         /* Ensure hash/chain table insertion resumes no sooner than lowlimit */
         if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
 
-        {   size_t cSize = ZSTD_compressBlock_internal(cctx,
-                                op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
-                                ip, blockSize, 1 /* frame */);
-            FORWARD_IF_ERROR(cSize);
-            if (cSize == 0) {  /* block is not compressible */
-                cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
+        {   int useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams);
+            size_t cSize = 0;
+            if (useTargetCBlockSize) {
+                cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);
                 FORWARD_IF_ERROR(cSize);
             } else {
-                const U32 cBlockHeader = cSize == 1 ?
-                    lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
-                    lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
-                MEM_writeLE24(op, cBlockHeader);
-                cSize += ZSTD_blockHeaderSize;
+                cSize = ZSTD_compressBlock_internal(cctx,
+                                        op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
+                                        ip, blockSize);
+                FORWARD_IF_ERROR(cSize);
+
+                if (cSize == 0) {  /* block is not compressible */
+                    cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
+                    FORWARD_IF_ERROR(cSize);
+                } else {
+                    U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
+                    MEM_writeLE24(op, cBlockHeader24);
+                    cSize += ZSTD_blockHeaderSize;
+                }
             }
 
+
             ip += blockSize;
             assert(remaining >= blockSize);
             remaining -= blockSize;
diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h
index 14036f873f5..b0230437cd1 100644
--- a/lib/compress/zstd_compress_internal.h
+++ b/lib/compress/zstd_compress_internal.h
@@ -336,6 +336,20 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
     return 1;
 }
 
+/* ZSTD_noCompressBlock() :
+ * Writes uncompressed block to dst buffer from given src.
+ * Returns the size of the block */
+MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
+{
+    U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
+    RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
+                    dstSize_tooSmall);
+    MEM_writeLE24(dst, cBlockHeader24);
+    memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
+    return ZSTD_blockHeaderSize + srcSize;
+}
+
+
 /* ZSTD_minGain() :
  * minimum compression required
  * to generate a compress block or a compressed literals section.
diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c
index 0ff7a26823b..950471c45f9 100644
--- a/lib/compress/zstd_compress_sequences.c
+++ b/lib/compress/zstd_compress_sequences.c
@@ -86,7 +86,7 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
  * Returns the cost in bits of encoding the distribution in count using ctable.
  * Returns an error if ctable cannot represent all the symbols in count.
  */
-static size_t ZSTD_fseBitCost(
+size_t ZSTD_fseBitCost(
     FSE_CTable const* ctable,
     unsigned const* count,
     unsigned const max)
@@ -117,8 +117,8 @@ static size_t ZSTD_fseBitCost(
  * table described by norm. The max symbol support by norm is assumed >= max.
  * norm must be valid for every symbol with non-zero probability in count.
  */
-static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
-                                    unsigned const* count, unsigned const max)
+size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
+                             unsigned const* count, unsigned const max)
 {
     unsigned const shift = 8 - accuracyLog;
     size_t cost = 0;
diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h
index 57e8e367b09..10cf678151a 100644
--- a/lib/compress/zstd_compress_sequences.h
+++ b/lib/compress/zstd_compress_sequences.h
@@ -44,4 +44,11 @@ size_t ZSTD_encodeSequences(
             FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
             seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2);
 
+size_t ZSTD_fseBitCost(
+    FSE_CTable const* ctable,
+    unsigned const* count,
+    unsigned const max);
+
+size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
+                             unsigned const* count, unsigned const max);
 #endif /* ZSTD_COMPRESS_SEQUENCES_H */
diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c
new file mode 100644
index 00000000000..cb6b6c26b51
--- /dev/null
+++ b/lib/compress/zstd_compress_superblock.c
@@ -0,0 +1,739 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+ /*-*************************************
+ *  Dependencies
+ ***************************************/
+#include "hist.h"           /* HIST_countFast_wksp */
+#include "zstd_compress_internal.h"
+#include "zstd_compress_superblock.h"
+#include "zstd_compress_sequences.h"
+#include "zstd_compress_literals.h"
+
+/*-*************************************
+*  Superblock entropy buffer structs
+***************************************/
+/** ZSTD_hufCTablesMetadata_t :
+ *  Stores Literals Block Type for a super-block in hType, and
+ *  huffman tree description in hufDesBuffer.
+ *  hufDesSize refers to the size of huffman tree description in bytes.
+ *  This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
+typedef struct {
+    symbolEncodingType_e hType;
+    BYTE hufDesBuffer[500]; // TODO give name to this value
+    size_t hufDesSize;
+} ZSTD_hufCTablesMetadata_t;
+
+/** ZSTD_fseCTablesMetadata_t :
+ *  Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
+ *  fse tables in fseTablesBuffer.
+ *  fseTablesSize refers to the size of fse tables in bytes.
+ *  This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */
+typedef struct {
+    symbolEncodingType_e llType;
+    symbolEncodingType_e ofType;
+    symbolEncodingType_e mlType;
+    BYTE fseTablesBuffer[500]; // TODO give name to this value
+    size_t fseTablesSize;
+    size_t lastCountSize; // This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences()
+} ZSTD_fseCTablesMetadata_t;
+
+typedef struct {
+    ZSTD_hufCTablesMetadata_t hufMetadata;
+    ZSTD_fseCTablesMetadata_t fseMetadata;
+} ZSTD_entropyCTablesMetadata_t;
+
+
+/** ZSTD_buildSuperBlockEntropy_literal() :
+ *  Builds entropy for the super-block literals.
+ *  Stores literals block type (raw, rle, compressed) and
+ *  huffman description table to hufMetadata.
+ *  Currently, this does not consider the option of reusing huffman table from
+ *  previous super-block. I think it would be a good improvement to add that option.
+ *  @return : size of huffman description table or error code */
+static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize,
+                                            const ZSTD_hufCTables_t* prevHuf,
+                                                  ZSTD_hufCTables_t* nextHuf,
+                                                  ZSTD_hufCTablesMetadata_t* hufMetadata,
+                                                  void* workspace, size_t wkspSize)
+{
+    BYTE* const wkspStart = (BYTE*)workspace;
+    BYTE* const wkspEnd = wkspStart + wkspSize;
+    BYTE* const countWkspStart = wkspStart;
+    unsigned* const countWksp = (unsigned*)workspace;
+    const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
+    BYTE* const nodeWksp = countWkspStart + countWkspSize;
+    const size_t nodeWkspSize = wkspEnd-nodeWksp;
+    unsigned maxSymbolValue = 255;
+    unsigned huffLog = 11;
+
+    DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
+
+    /* Prepare nextEntropy assuming reusing the existing table */
+    memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+
+    /* small ? don't even attempt compression (speed opt) */
+#   define COMPRESS_LITERALS_SIZE_MIN 63
+    {   size_t const minLitSize = COMPRESS_LITERALS_SIZE_MIN;
+        if (srcSize <= minLitSize) { hufMetadata->hType = set_basic; return 0; }
+    }
+
+    /* Scan input and build symbol stats */
+    {   size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
+        FORWARD_IF_ERROR(largest);
+        if (largest == srcSize) { hufMetadata->hType = set_rle; return 0; }
+        if (largest <= (srcSize >> 7)+4) { hufMetadata->hType = set_basic; return 0; }
+    }
+
+
+    /* Build Huffman Tree */
+    memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
+    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
+    {   size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
+                                                    maxSymbolValue, huffLog,
+                                                    nodeWksp, nodeWkspSize);
+        FORWARD_IF_ERROR(maxBits);
+        huffLog = (U32)maxBits;
+        {   size_t cSize = HUF_estimateCompressedSize(
+                              (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
+            size_t hSize = HUF_writeCTable(
+                              hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
+                              (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog);
+            if (cSize + hSize >= srcSize) { hufMetadata->hType = set_basic; return 0; }
+            hufMetadata->hType = set_compressed;
+            return hSize;
+        }
+    }
+}
+
+/** ZSTD_buildSuperBlockEntropy_sequences() :
+ *  Builds entropy for the super-block sequences.
+ *  Stores symbol compression modes and fse table to fseMetadata.
+ *  @return : size of fse tables or error code */
+static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
+                                              const ZSTD_fseCTables_t* prevEntropy,
+                                                    ZSTD_fseCTables_t* nextEntropy,
+                                              const ZSTD_CCtx_params* cctxParams,
+                                                    ZSTD_fseCTablesMetadata_t* fseMetadata,
+                                                    void* workspace, size_t wkspSize)
+{
+    BYTE* const wkspStart = (BYTE*)workspace;
+    BYTE* const wkspEnd = wkspStart + wkspSize;
+    BYTE* const countWkspStart = wkspStart;
+    unsigned* const countWksp = (unsigned*)workspace;
+    const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned);
+    BYTE* const cTableWksp = countWkspStart + countWkspSize;
+    const size_t cTableWkspSize = wkspEnd-cTableWksp;
+    ZSTD_strategy const strategy = cctxParams->cParams.strategy;
+    FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
+    FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
+    FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
+    const BYTE* const ofCodeTable = seqStorePtr->ofCode;
+    const BYTE* const llCodeTable = seqStorePtr->llCode;
+    const BYTE* const mlCodeTable = seqStorePtr->mlCode;
+    size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
+    BYTE* const ostart = fseMetadata->fseTablesBuffer;
+    BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
+    BYTE* op = ostart;
+
+    assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
+    DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
+    memset(workspace, 0, wkspSize);
+
+    fseMetadata->lastCountSize = 0;
+    /* convert length/distances into codes */
+    ZSTD_seqToCodes(seqStorePtr);
+    /* build CTable for Literal Lengths */
+    {   U32 LLtype;
+        unsigned max = MaxLL;
+        size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize);  /* can't fail */
+        DEBUGLOG(5, "Building LL table");
+        nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
+        LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
+                                        countWksp, max, mostFrequent, nbSeq,
+                                        LLFSELog, prevEntropy->litlengthCTable,
+                                        LL_defaultNorm, LL_defaultNormLog,
+                                        ZSTD_defaultAllowed, strategy);
+        assert(set_basic < set_compressed && set_rle < set_compressed);
+        assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        {   size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
+                                                    countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
+                                                    prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
+                                                    cTableWksp, cTableWkspSize);
+            FORWARD_IF_ERROR(countSize);
+            if (LLtype == set_compressed)
+                fseMetadata->lastCountSize = countSize;
+            op += countSize;
+            fseMetadata->llType = (symbolEncodingType_e) LLtype;
+    }   }
+    /* build CTable for Offsets */
+    {   U32 Offtype;
+        unsigned max = MaxOff;
+        size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize);  /* can't fail */
+        /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
+        ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
+        DEBUGLOG(5, "Building OF table");
+        nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
+        Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
+                                        countWksp, max, mostFrequent, nbSeq,
+                                        OffFSELog, prevEntropy->offcodeCTable,
+                                        OF_defaultNorm, OF_defaultNormLog,
+                                        defaultPolicy, strategy);
+        assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        {   size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
+                                                    countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
+                                                    prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
+                                                    cTableWksp, cTableWkspSize);
+            FORWARD_IF_ERROR(countSize);
+            if (Offtype == set_compressed)
+                fseMetadata->lastCountSize = countSize;
+            op += countSize;
+            fseMetadata->ofType = (symbolEncodingType_e) Offtype;
+    }   }
+    /* build CTable for MatchLengths */
+    {   U32 MLtype;
+        unsigned max = MaxML;
+        size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize);   /* can't fail */
+        DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
+        nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
+        MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
+                                        countWksp, max, mostFrequent, nbSeq,
+                                        MLFSELog, prevEntropy->matchlengthCTable,
+                                        ML_defaultNorm, ML_defaultNormLog,
+                                        ZSTD_defaultAllowed, strategy);
+        assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+        {   size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
+                                                    countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
+                                                    prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
+                                                    cTableWksp, cTableWkspSize);
+            FORWARD_IF_ERROR(countSize);
+            if (MLtype == set_compressed)
+                fseMetadata->lastCountSize = countSize;
+            op += countSize;
+            fseMetadata->mlType = (symbolEncodingType_e) MLtype;
+    }   }
+    assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer));
+    return op-ostart;
+}
+
+
+/** ZSTD_buildSuperBlockEntropy() :
+ *  Builds entropy for the super-block.
+ *  @return : 0 on success or error code */
+static size_t
+ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
+                      const ZSTD_entropyCTables_t* prevEntropy,
+                            ZSTD_entropyCTables_t* nextEntropy,
+                      const ZSTD_CCtx_params* cctxParams,
+                            ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+                            void* workspace, size_t wkspSize)
+{
+    size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
+    DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy");
+    entropyMetadata->hufMetadata.hufDesSize =
+        ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize,
+                                            &prevEntropy->huf, &nextEntropy->huf,
+                                            &entropyMetadata->hufMetadata,
+                                            workspace, wkspSize);
+    FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize);
+    entropyMetadata->fseMetadata.fseTablesSize =
+        ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr,
+                                              &prevEntropy->fse, &nextEntropy->fse,
+                                              cctxParams,
+                                              &entropyMetadata->fseMetadata,
+                                              workspace, wkspSize);
+    FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize);
+    return 0;
+}
+
+/** ZSTD_compressSubBlock_literal() :
+ *  Compresses literals section for a sub-block.
+ *  Compressed literal size needs to be less than uncompressed literal size.
+ *      ZSTD spec doesn't have this constaint. I will explain why I have this constraint here.
+ *      Literals section header size ranges from 1 to 5 bytes,
+ *      which is dictated by regenerated size and compressed size.
+ *      In order to figure out the memory address to start writing compressed literal,
+ *      it is necessary to figure out the literals section header size.
+ *      The challenge is that compressed size is only known after compression.
+ *      This is a chicken and egg problem.
+ *      I am simplifying the problem by assuming that
+ *      compressed size will always be less than or equal to regenerated size,
+ *      and using regenerated size to calculate literals section header size.
+ *  hufMetadata->hType has literals block type info.
+ *      If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block.
+ *      If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block.
+ *      If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block
+ *      and the following sub-blocks' literals sections will be Treeless_Literals_Block.
+ *  @return : compressed size of literals section of a sub-block
+ *            Or 0 if it unable to compress.
+ *            Or error code */
+static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
+                                    const ZSTD_hufCTablesMetadata_t* hufMetadata,
+                                    const BYTE* literals, size_t litSize,
+                                    void* dst, size_t dstSize,
+                                    const int bmi2, int writeEntropy)
+{
+    size_t const lhSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB);
+    BYTE* const ostart = (BYTE*)dst;
+    BYTE* const oend = ostart + dstSize;
+    BYTE* op = ostart + lhSize;
+    U32 singleStream = litSize < 256;
+    symbolEncodingType_e hType = writeEntropy ? set_compressed : set_repeat;
+    size_t cLitSize = 0;
+
+    (void)bmi2; // TODO bmi2...
+
+    DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy);
+
+    if (writeEntropy && litSize == 0) {
+      /* Literals section cannot be compressed mode when litSize == 0.
+       * (This seems to be decoder constraint.)
+       * Entropy cannot be written if literals section is not compressed mode.
+       */
+      return 0;
+    }
+
+    if (litSize == 0 || hufMetadata->hType == set_basic) {
+      DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal");
+      return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
+    } else if (hufMetadata->hType == set_rle) {
+      DEBUGLOG(5, "ZSTD_compressSubBlock_literal using rle literal");
+      return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize);
+    }
+
+    if (lhSize == 3) singleStream = 1;
+    if (writeEntropy) {
+        memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
+        op += hufMetadata->hufDesSize;
+        cLitSize += hufMetadata->hufDesSize;
+        DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
+    }
+
+    // TODO bmi2
+    {   const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable)
+                                          : HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable);
+        op += cSize;
+        cLitSize += cSize;
+        if (cSize == 0 || ERR_isError(cSize)) {
+          return 0;
+        }
+        if (cLitSize > litSize) {
+            if (writeEntropy) return 0;
+            else return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);
+        }
+        DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize);
+    }
+
+    /* Build header */
+    switch(lhSize)
+    {
+    case 3: /* 2 - 2 - 10 - 10 */
+        {   U32 const lhc = hType + ((!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);
+            MEM_writeLE24(ostart, lhc);
+            break;
+        }
+    case 4: /* 2 - 2 - 14 - 14 */
+        {   U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18);
+            MEM_writeLE32(ostart, lhc);
+            break;
+        }
+    case 5: /* 2 - 2 - 18 - 18 */
+        {   U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22);
+            MEM_writeLE32(ostart, lhc);
+            ostart[4] = (BYTE)(cLitSize >> 10);
+            break;
+        }
+    default:  /* not possible : lhSize is {3,4,5} */
+        assert(0);
+    }
+    return op-ostart;
+}
+
+static size_t ZSTD_seqDecompressedSize(const seqDef* sequences, size_t nbSeq, size_t litSize) {
+    const seqDef* const sstart = sequences;
+    const seqDef* const send = sequences + nbSeq;
+    const seqDef* sp = sstart;
+    size_t matchLengthSum = 0;
+    while (send-sp > 0) {
+      matchLengthSum += sp->matchLength + MINMATCH;
+      sp++;
+    }
+    return matchLengthSum + litSize;
+}
+
+/** ZSTD_compressSubBlock_sequences() :
+ *  Compresses sequences section for a sub-block.
+ *  fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have
+ *  symbol compression modes for the super-block.
+ *  First sub-block will have these in its header. The following sub-blocks
+ *  will always have repeat mode.
+ *  @return : compressed size of sequences section of a sub-block
+ *            Or 0 if it is unable to compress
+ *            Or error code. */
+static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,
+                                              const ZSTD_fseCTablesMetadata_t* fseMetadata,
+                                              const seqDef* sequences, size_t nbSeq,
+                                              const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
+                                              const ZSTD_CCtx_params* cctxParams,
+                                              void* dst, size_t dstCapacity,
+                                              const int bmi2, int writeEntropy)
+{
+    const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
+    BYTE* const ostart = (BYTE*)dst;
+    BYTE* const oend = ostart + dstCapacity;
+    BYTE* op = ostart;
+    BYTE* seqHead;
+
+    DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets);
+
+    /* Sequences Header */
+    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
+                    dstSize_tooSmall);
+    if (nbSeq < 0x7F)
+        *op++ = (BYTE)nbSeq;
+    else if (nbSeq < LONGNBSEQ)
+        op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
+    else
+        op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
+    if (writeEntropy && nbSeq == 0) {
+        return 0;
+    }
+    if (nbSeq==0) {
+        return op - ostart;
+    }
+
+    /* seqHead : flags for FSE encoding type */
+    seqHead = op++;
+
+    DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (seqHeadSize=%u)", (unsigned)(op-ostart));
+
+    if (writeEntropy) {
+        const U32 LLtype = fseMetadata->llType;
+        const U32 Offtype = fseMetadata->ofType;
+        const U32 MLtype = fseMetadata->mlType;
+        DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
+        *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
+        memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
+        op += fseMetadata->fseTablesSize;
+    } else {
+        const U32 repeat = set_repeat;
+        *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2));
+    }
+
+    {   size_t const bitstreamSize = ZSTD_encodeSequences(
+                                        op, oend - op,
+                                        fseTables->matchlengthCTable, mlCode,
+                                        fseTables->offcodeCTable, ofCode,
+                                        fseTables->litlengthCTable, llCode,
+                                        sequences, nbSeq,
+                                        longOffsets, bmi2);
+        FORWARD_IF_ERROR(bitstreamSize);
+        op += bitstreamSize;
+        /* zstd versions <= 1.3.4 mistakenly report corruption when
+         * FSE_readNCount() receives a buffer < 4 bytes.
+         * Fixed by https://github.com/facebook/zstd/pull/1146.
+         * This can happen when the last set_compressed table present is 2
+         * bytes and the bitstream is only one byte.
+         * In this exceedingly rare case, we will simply emit an uncompressed
+         * block, since it isn't worth optimizing.
+         */
+        if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {
+            /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
+            assert(fseMetadata->lastCountSize + bitstreamSize == 3);
+            DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
+                        "emitting an uncompressed block.");
+            return 0;
+        }
+        DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize);
+    }
+
+    /* zstd versions <= 1.4.0 mistakenly report error when
+     * sequences section body size is less than 3 bytes.
+     * Fixed by https://github.com/facebook/zstd/pull/1664.
+     * This can happen when the previous sequences section block is compressed
+     * with rle mode and the current block's sequences section is compressed
+     * with repeat mode where sequences section body size can be 1 byte.
+     */
+    if (op-seqHead < 4) {
+        return 0;
+    }
+
+    return op - ostart;
+}
+
+/** ZSTD_compressSubBlock() :
+ *  Compresses a single sub-block.
+ *  @return : compressed size of the sub-block
+ *            Or 0 if it failed to compress. */
+static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,
+                                    const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+                                    const seqDef* sequences, size_t nbSeq,
+                                    const BYTE* literals, size_t litSize,
+                                    const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,
+                                    const ZSTD_CCtx_params* cctxParams,
+                                    void* dst, size_t dstCapacity,
+                                    const int bmi2, int writeEntropy, U32 lastBlock)
+{
+    BYTE* const ostart = (BYTE*)dst;
+    BYTE* const oend = ostart + dstCapacity;
+    BYTE* op = ostart + ZSTD_blockHeaderSize;
+    DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeEntropy=%d, lastBlock=%d)",
+                litSize, nbSeq, writeEntropy, lastBlock);
+    {   size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,
+                                                        &entropyMetadata->hufMetadata, literals, litSize,
+                                                        op, oend-op, bmi2, writeEntropy);
+        FORWARD_IF_ERROR(cLitSize);
+        if (cLitSize == 0) return 0;
+        op += cLitSize;
+    }
+    {   size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse,
+                                                  &entropyMetadata->fseMetadata,
+                                                  sequences, nbSeq,
+                                                  llCode, mlCode, ofCode,
+                                                  cctxParams,
+                                                  op, oend-op,
+                                                  bmi2, writeEntropy);
+        FORWARD_IF_ERROR(cSeqSize);
+        if (cSeqSize == 0) return 0;
+        op += cSeqSize;
+    }
+    /* Write block header */
+    {   size_t cSize = (op-ostart)-ZSTD_blockHeaderSize;
+        U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
+        MEM_writeLE24(ostart, cBlockHeader24);
+    }
+    return op-ostart;
+}
+
+static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,
+                                                const ZSTD_hufCTables_t* huf,
+                                                const ZSTD_hufCTablesMetadata_t* hufMetadata,
+                                                void* workspace, size_t wkspSize,
+                                                int writeEntropy)
+{
+    unsigned* const countWksp = (unsigned*)workspace;
+    unsigned maxSymbolValue = 255;
+    size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
+
+    if (hufMetadata->hType == set_basic) return litSize;
+    else if (hufMetadata->hType == set_rle) return 1;
+    else if (hufMetadata->hType == set_compressed) {
+        size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);
+        if (ZSTD_isError(largest)) return litSize;
+        {   size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);
+            if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;
+            return cLitSizeEstimate + literalSectionHeaderSize;
+    }   }
+    assert(0); /* impossible */
+    return 0;
+}
+
+static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
+                        const BYTE* codeTable, unsigned maxCode,
+                        size_t nbSeq, const FSE_CTable* fseCTable,
+                        const U32* additionalBits,
+                        short const* defaultNorm, U32 defaultNormLog,
+                        void* workspace, size_t wkspSize)
+{
+    unsigned* const countWksp = (unsigned*)workspace;
+    const BYTE* ctp = codeTable;
+    const BYTE* const ctStart = ctp;
+    const BYTE* const ctEnd = ctStart + nbSeq;
+    size_t cSymbolTypeSizeEstimateInBits = 0;
+    unsigned max = maxCode;
+
+    HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize);  /* can't fail */
+    if (type == set_basic) {
+        cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);
+    } else if (type == set_rle) {
+        cSymbolTypeSizeEstimateInBits = 0;
+    } else if (type == set_compressed || type == set_repeat) {
+        cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);
+    }
+    if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10;
+    while (ctp < ctEnd) {
+        if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];
+        else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */
+        ctp++;
+    }
+    return cSymbolTypeSizeEstimateInBits / 8;
+}
+
+static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
+                                                  const BYTE* llCodeTable,
+                                                  const BYTE* mlCodeTable,
+                                                  size_t nbSeq,
+                                                  const ZSTD_fseCTables_t* fseTables,
+                                                  const ZSTD_fseCTablesMetadata_t* fseMetadata,
+                                                  void* workspace, size_t wkspSize,
+                                                  int writeEntropy)
+{
+    size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
+    size_t cSeqSizeEstimate = 0;
+    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
+                                         nbSeq, fseTables->offcodeCTable, NULL,
+                                         OF_defaultNorm, OF_defaultNormLog,
+                                         workspace, wkspSize);
+    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
+                                         nbSeq, fseTables->litlengthCTable, LL_bits,
+                                         LL_defaultNorm, LL_defaultNormLog,
+                                         workspace, wkspSize);
+    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
+                                         nbSeq, fseTables->matchlengthCTable, ML_bits,
+                                         ML_defaultNorm, ML_defaultNormLog,
+                                         workspace, wkspSize);
+    if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
+    return cSeqSizeEstimate + sequencesSectionHeaderSize;
+}
+
+static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,
+                                        const BYTE* ofCodeTable,
+                                        const BYTE* llCodeTable,
+                                        const BYTE* mlCodeTable,
+                                        size_t nbSeq,
+                                        const ZSTD_entropyCTables_t* entropy,
+                                        const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+                                        void* workspace, size_t wkspSize,
+                                        int writeEntropy) {
+    size_t cSizeEstimate = 0;
+    cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize,
+                                                         &entropy->huf, &entropyMetadata->hufMetadata,
+                                                         workspace, wkspSize, writeEntropy);
+    cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
+                                                         nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
+                                                         workspace, wkspSize, writeEntropy);
+    return cSizeEstimate + ZSTD_blockHeaderSize;
+}
+
+/** ZSTD_compressSubBlock_multi() :
+ *  Breaks super-block into multiple sub-blocks and compresses them.
+ *  Entropy will be written to the first block.
+ *  The following blocks will use repeat mode to compress.
+ *  All sub-blocks are compressed blocks (no raw or rle blocks).
+ *  @return : compressed size of the super block (which is multiple ZSTD blocks)
+ *            Or 0 if it failed to compress. */
+static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
+                            const ZSTD_entropyCTables_t* entropy,
+                            const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+                            const ZSTD_CCtx_params* cctxParams,
+                                  void* dst, size_t dstCapacity,
+                            const int bmi2, U32 lastBlock,
+                            void* workspace, size_t wkspSize)
+{
+    const seqDef* const sstart = seqStorePtr->sequencesStart;
+    const seqDef* const send = seqStorePtr->sequences;
+    const seqDef* sp = sstart;
+    const BYTE* const lstart = seqStorePtr->litStart;
+    const BYTE* const lend = seqStorePtr->lit;
+    const BYTE* lp = lstart;
+    BYTE* const ostart = (BYTE*)dst;
+    BYTE* const oend = ostart + dstCapacity;
+    BYTE* op = ostart;
+    const BYTE* llCodePtr = seqStorePtr->llCode;
+    const BYTE* mlCodePtr = seqStorePtr->mlCode;
+    const BYTE* ofCodePtr = seqStorePtr->ofCode;
+    size_t targetCBlockSize = cctxParams->targetCBlockSize;
+    size_t litSize, seqCount;
+    int writeEntropy = 1;
+    size_t remaining = ZSTD_seqDecompressedSize(sstart, send-sstart, lend-lstart);
+    size_t cBlockSizeEstimate = 0;
+
+    DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)",
+                (unsigned)(lend-lp), (unsigned)(send-sstart));
+
+    litSize = 0;
+    seqCount = 0;
+    while (sp + seqCount < send) {
+        // TODO this is crude estimate for now...
+        // Ask Yann, Nick for feedback.
+        const seqDef* const sequence = sp + seqCount;
+        const U32 lastSequence = sequence+1 == send;
+        litSize = (sequence == send) ? (size_t)(lend-lp) : litSize + sequence->litLength;
+        seqCount++;
+        cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
+                                                       entropy, entropyMetadata,
+                                                       workspace, wkspSize, writeEntropy);
+        if (cBlockSizeEstimate > targetCBlockSize || lastSequence) {
+            const size_t decompressedSize = ZSTD_seqDecompressedSize(sp, seqCount, litSize);
+            const size_t cSize = ZSTD_compressSubBlock(entropy, entropyMetadata,
+                                                       sp, seqCount,
+                                                       lp, litSize,
+                                                       llCodePtr, mlCodePtr, ofCodePtr,
+                                                       cctxParams,
+                                                       op, oend-op,
+                                                       bmi2, writeEntropy, lastBlock && lastSequence);
+            FORWARD_IF_ERROR(cSize);
+            if (cSize > 0 && cSize < decompressedSize) {
+                assert(remaining >= decompressedSize);
+                remaining -= decompressedSize;
+                sp += seqCount;
+                lp += litSize;
+                op += cSize;
+                llCodePtr += seqCount;
+                mlCodePtr += seqCount;
+                ofCodePtr += seqCount;
+                litSize = 0;
+                seqCount = 0;
+                writeEntropy = 0; // Entropy only needs to be written once
+            }
+        }
+    }
+    if (remaining) {
+        DEBUGLOG(5, "ZSTD_compressSubBlock_multi failed to compress");
+        return 0;
+    }
+    DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
+    return op-ostart;
+}
+
+size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
+                               void* dst, size_t dstCapacity,
+                               unsigned lastBlock) {
+    ZSTD_entropyCTablesMetadata_t entropyMetadata;
+
+    FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore,
+          &zc->blockState.prevCBlock->entropy,
+          &zc->blockState.nextCBlock->entropy,
+          &zc->appliedParams,
+          &entropyMetadata,
+          zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */));
+
+    return ZSTD_compressSubBlock_multi(&zc->seqStore,
+            &zc->blockState.nextCBlock->entropy,
+            &entropyMetadata,
+            &zc->appliedParams,
+            dst, dstCapacity,
+            zc->bmi2, lastBlock,
+            zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
+}
+
+size_t ZSTD_noCompressSuperBlock(void* dst, size_t dstCapacity,
+                                 const void* src, size_t srcSize,
+                                 size_t targetCBlockSize,
+                                 unsigned lastBlock) {
+    const BYTE* const istart = (const BYTE*)src;
+    const BYTE* const iend = istart + srcSize;
+    const BYTE* ip = istart;
+    BYTE* const ostart = (BYTE*)dst;
+    BYTE* const oend = ostart + dstCapacity;
+    BYTE* op = ostart;
+    DEBUGLOG(5, "ZSTD_noCompressSuperBlock (dstCapacity=%zu, srcSize=%zu, targetCBlockSize=%zu)",
+                dstCapacity, srcSize, targetCBlockSize);
+    while (ip < iend) {
+        size_t remaining = iend-ip;
+        unsigned lastSubBlock = remaining <= targetCBlockSize;
+        size_t blockSize = lastSubBlock ? remaining : targetCBlockSize;
+        size_t cSize = ZSTD_noCompressBlock(op, oend-op, ip, blockSize, lastSubBlock && lastBlock);
+        FORWARD_IF_ERROR(cSize);
+        ip += blockSize;
+        op += cSize;
+    }
+    return op-ostart;
+}
diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h
new file mode 100644
index 00000000000..b1d72ec4ed8
--- /dev/null
+++ b/lib/compress/zstd_compress_superblock.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_COMPRESS_ADVANCED_H
+#define ZSTD_COMPRESS_ADVANCED_H
+
+/*-*************************************
+*  Dependencies
+***************************************/
+
+#include "zstd.h" /* ZSTD_CCtx */
+
+/*-*************************************
+*  Target Compressed Block Size
+***************************************/
+
+/* ZSTD_compressSuperBlock() :
+ * Used to compress a super block when targetCBlockSize is being used.
+ * The given block will be compressed into multiple sub blocks that are around targetCBlockSize. */
+size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
+                               void* dst, size_t dstCapacity,
+                               unsigned lastBlock);
+
+/* ZSTD_noCompressSuperBlock() :
+* Used to break a super block into multiple uncompressed sub blocks
+* when targetCBlockSize is being used.
+* The given block will be broken into multiple uncompressed sub blocks that are
+* around targetCBlockSize. */
+size_t ZSTD_noCompressSuperBlock(void* dst, size_t dstCapacity,
+                                 const void* src, size_t srcSize,
+                                 size_t targetCBlockSize,
+                                 unsigned lastBlock);
+
+#endif /* ZSTD_COMPRESS_ADVANCED_H */

From f2932fb5ebfb16fa6474edbce74d27452f1da18a Mon Sep 17 00:00:00 2001
From: Sen Huang 
Date: Tue, 5 Nov 2019 15:54:05 -0500
Subject: [PATCH 034/402] Fix more merge conflicts

---
 lib/compress/zstd_compress_superblock.c | 7 +++++--
 tests/fuzz/dictionary_round_trip.c      | 2 +-
 tests/fuzz/simple_round_trip.c          | 2 +-
 tests/fuzz/zstd_helpers.c               | 3 +++
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c
index cb6b6c26b51..3dfb16dee3b 100644
--- a/lib/compress/zstd_compress_superblock.c
+++ b/lib/compress/zstd_compress_superblock.c
@@ -651,12 +651,15 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
     litSize = 0;
     seqCount = 0;
     while (sp + seqCount < send) {
-        // TODO this is crude estimate for now...
-        // Ask Yann, Nick for feedback.
         const seqDef* const sequence = sp + seqCount;
         const U32 lastSequence = sequence+1 == send;
         litSize = (sequence == send) ? (size_t)(lend-lp) : litSize + sequence->litLength;
         seqCount++;
+        /* I think there is an optimization opportunity here.
+         * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful
+         * since it recalculates estimate from scratch.
+         * For example, it would recount literal distribution and symbol codes everytime. 
+         */
         cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
                                                        entropy, entropyMetadata,
                                                        workspace, wkspSize, writeEntropy);
diff --git a/tests/fuzz/dictionary_round_trip.c b/tests/fuzz/dictionary_round_trip.c
index 9411b50a74e..4a32b82be78 100644
--- a/tests/fuzz/dictionary_round_trip.c
+++ b/tests/fuzz/dictionary_round_trip.c
@@ -73,7 +73,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 
     size_t const rBufSize = size;
     void* rBuf = malloc(rBufSize);
-    size_t cBufSize = ZSTD_compressBound(size);
+    size_t cBufSize = ZSTD_compressBound(size) * 2;
     void *cBuf;
     /* Half of the time fuzz with a 1 byte smaller output size.
      * This will still succeed because we force the checksum to be disabled,
diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c
index 2d1d0598a14..6a65b19087e 100644
--- a/tests/fuzz/simple_round_trip.c
+++ b/tests/fuzz/simple_round_trip.c
@@ -48,7 +48,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 {
     size_t const rBufSize = size;
     void* rBuf = malloc(rBufSize);
-    size_t cBufSize = ZSTD_compressBound(size);
+    size_t cBufSize = ZSTD_compressBound(size) * 2;
     void* cBuf;
 
     /* Give a random portion of src data to the producer, to use for
diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c
index 90bf1a15678..41de2202096 100644
--- a/tests/fuzz/zstd_helpers.c
+++ b/tests/fuzz/zstd_helpers.c
@@ -96,6 +96,9 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer
     if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {
       setRand(cctx, ZSTD_c_srcSizeHint, ZSTD_SRCSIZEHINT_MIN, 2 * srcSize, producer);
     }
+    if (FUZZ_rand32(producer, 0, 1)) {
+        setRand(cctx, ZSTD_c_targetCBlockSize, ZSTD_TARGETCBLOCKSIZE_MIN, ZSTD_TARGETCBLOCKSIZE_MAX, producer);
+    }
 }
 
 FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *producer)

From 13bb7500e8751633c839e2004131f5a3951df0ea Mon Sep 17 00:00:00 2001
From: Sen Huang 
Date: Tue, 5 Nov 2019 16:15:55 -0500
Subject: [PATCH 035/402] Fix frame argument to compression

---
 lib/compress/zstd_compress.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
index 3364098404e..b8349d8bab4 100644
--- a/lib/compress/zstd_compress.c
+++ b/lib/compress/zstd_compress.c
@@ -2580,7 +2580,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
             } else {
                 cSize = ZSTD_compressBlock_internal(cctx,
                                         op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
-                                        ip, blockSize);
+                                        ip, blockSize, 0 /* frame */);
                 FORWARD_IF_ERROR(cSize);
 
                 if (cSize == 0) {  /* block is not compressible */

From e21a8bbecd244c688d16d56c76441e9bffbdd67c Mon Sep 17 00:00:00 2001
From: Sen Huang 
Date: Tue, 5 Nov 2019 16:43:24 -0500
Subject: [PATCH 036/402] Fix FUZZ_rand32() bug

---
 tests/fuzz/zstd_helpers.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c
index 41de2202096..313b463f783 100644
--- a/tests/fuzz/zstd_helpers.c
+++ b/tests/fuzz/zstd_helpers.c
@@ -96,8 +96,8 @@ void FUZZ_setRandomParameters(ZSTD_CCtx *cctx, size_t srcSize, FUZZ_dataProducer
     if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {
       setRand(cctx, ZSTD_c_srcSizeHint, ZSTD_SRCSIZEHINT_MIN, 2 * srcSize, producer);
     }
-    if (FUZZ_rand32(producer, 0, 1)) {
-        setRand(cctx, ZSTD_c_targetCBlockSize, ZSTD_TARGETCBLOCKSIZE_MIN, ZSTD_TARGETCBLOCKSIZE_MAX, producer);
+    if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) {
+      setRand(cctx, ZSTD_c_targetCBlockSize, ZSTD_TARGETCBLOCKSIZE_MIN, ZSTD_TARGETCBLOCKSIZE_MAX, producer);
     }
 }
 

From 76b9e42b0bc1e3e482a8033a664382764caf85fa Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Tue, 5 Nov 2019 14:59:45 -0800
Subject: [PATCH 037/402] refactoring (simplification) of util.h public API

---
 programs/util.c | 40 ++++++++++++++++++++++++++++-------
 programs/util.h | 56 ++++++++++++++++++++++---------------------------
 2 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index c9503e7ff42..23f37ccd2d4 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -24,6 +24,11 @@ extern "C" {
 #include      /* needed for _mkdir in windows */
 #endif
 
+#if defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */
+#  include        /* opendir, readdir */
+#  include        /* strerror, memcpy */
+#endif /* #ifdef _WIN32 */
+
 
 /*-****************************************
 *  Internal Macros
@@ -40,6 +45,19 @@ extern "C" {
 }   }
 
 
+/*
+ * A modified version of realloc().
+ * If UTIL_realloc() fails the original block is freed.
+ */
+UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)
+{
+    void *newptr = realloc(ptr, size);
+    if (newptr) return newptr;
+    free(ptr);
+    return NULL;
+}
+
+
 /*-****************************************
 *  Console log
 ******************************************/
@@ -385,9 +403,9 @@ UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2)
 }
 
 #ifdef _WIN32
-int UTIL_prepareFileList(const char* dirName,
-                         char** bufStart, size_t* pos,
-                         char** bufEnd, int followLinks)
+static int UTIL_prepareFileList(const char* dirName,
+                                char** bufStart, size_t* pos,
+                                char** bufEnd, int followLinks)
 {
     char* path;
     size_t dirLength, pathLength;
@@ -450,9 +468,9 @@ int UTIL_prepareFileList(const char* dirName,
 
 #elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */
 
-int UTIL_prepareFileList(const char *dirName,
-                         char** bufStart, size_t* pos,
-                         char** bufEnd, int followLinks)
+static int UTIL_prepareFileList(const char *dirName,
+                                char** bufStart, size_t* pos,
+                                char** bufEnd, int followLinks)
 {
     DIR* dir;
     struct dirent * entry;
@@ -518,7 +536,9 @@ int UTIL_prepareFileList(const char *dirName,
 
 #else
 
-int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
+static int UTIL_prepareFileList(const char *dirName,
+                                char** bufStart, size_t* pos,
+                                char** bufEnd, int followLinks)
 {
     (void)bufStart; (void)bufEnd; (void)pos; (void)followLinks;
     UTIL_DISPLAYLEVEL(1, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
@@ -605,6 +625,12 @@ UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
 }
 
 
+void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)
+{
+    if (allocatedBuffer) free(allocatedBuffer);
+    if (filenameTable) free((void*)filenameTable);
+}
+
 
 
 /*-****************************************
diff --git a/programs/util.h b/programs/util.h
index d6c2ecf016b..93780a4fea3 100644
--- a/programs/util.h
+++ b/programs/util.h
@@ -146,7 +146,20 @@ U64 UTIL_getFileSize(const char* infilename);
 
 U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles);
 
-/*Note: tableSize is denotes the total capacity of table*/
+
+/*-****************************************
+ *  Lists of Filenames
+ ******************************************/
+
+#ifdef _WIN32
+#  define UTIL_HAS_CREATEFILELIST
+#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */
+#  define UTIL_HAS_CREATEFILELIST
+#else
+   /* do not define UTIL_HAS_CREATEFILELIST */
+#endif /* #ifdef _WIN32 */
+
+/*Note: tableSize denotes the total capacity of table*/
 typedef struct
 {
     const char** fileNames;
@@ -183,48 +196,29 @@ void UTIL_freeFileNamesTable(FileNamesTable* table);
 FileNamesTable*
 UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2);
 
-/*
- * A modified version of realloc().
- * If UTIL_realloc() fails the original block is freed.
-*/
-UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)
-{
-    void *newptr = realloc(ptr, size);
-    if (newptr) return newptr;
-    free(ptr);
-    return NULL;
-}
-
-int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks);
-#ifdef _WIN32
-#  define UTIL_HAS_CREATEFILELIST
-#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */
-#  define UTIL_HAS_CREATEFILELIST
-#  include        /* opendir, readdir */
-#  include        /* strerror, memcpy */
-#else
-#endif /* #ifdef _WIN32 */
 
 /*
  * UTIL_createFileList() :
- * takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
- * and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
- * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
- * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
+ * takes a list of files and directories (@inputNames, @inputNamesNb),
+ * scans directories, and returns a new list of files (@return, @allocatedBuffer, @allocatedNamesNb).
+ * In case of error, UTIL_createFileList() returns NULL.
+ * After list's end of life, the structures should be freed with UTIL_freeFileList (@return, @allocatedBuffer).
  */
 const char**
 UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
                     char** allocatedBuffer, unsigned* allocatedNamesNb,
                     int followLinks);
 
-UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)
-{
-    if (allocatedBuffer) free(allocatedBuffer);
-    if (filenameTable) free((void*)filenameTable);
-}
+void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer);
+
+
+/*-****************************************
+ *  System
+ ******************************************/
 
 int UTIL_countPhysicalCores(void);
 
+
 #if defined (__cplusplus)
 }
 #endif

From b09f59390bbda3481dd78f1ed885a89dedae9923 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Tue, 5 Nov 2019 17:02:43 -0800
Subject: [PATCH 038/402] refactor code to only use FileNamesTable*

---
 programs/util.c    | 101 ++++---
 programs/util.h    |  41 ++-
 programs/zstdcli.c | 675 +++++++++++++++++++++------------------------
 3 files changed, 395 insertions(+), 422 deletions(-)

diff --git a/programs/util.c b/programs/util.c
index 23f37ccd2d4..55ca5a68127 100644
--- a/programs/util.c
+++ b/programs/util.c
@@ -335,6 +335,7 @@ UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf)
     table->fileNames = filenames;
     table->buf = buf;
     table->tableSize = tableSize;
+    table->tableCapacity = tableSize;
     return table;
 }
 
@@ -346,6 +347,23 @@ void UTIL_freeFileNamesTable(FileNamesTable* table)
     free(table);
 }
 
+FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize)
+{
+    const char** const fnTable = (const char**)malloc(tableSize * sizeof(*fnTable));
+    FileNamesTable* fnt;
+    if (fnTable==NULL) return NULL;
+    fnt = UTIL_createFileNamesTable(fnTable, tableSize, NULL);
+    fnt->tableSize = 0;   /* the table is empty */
+    return fnt;
+}
+
+void UTIL_refFilename(FileNamesTable* fnt, const char* filename)
+{
+    if (fnt->tableCapacity <= fnt->tableSize) abort();
+    fnt->fileNames[fnt->tableSize] = filename;
+    fnt->tableSize++;
+}
+
 static size_t getTotalTableSize(FileNamesTable* table)
 {
     size_t fnb = 0, totalSize = 0;
@@ -568,71 +586,66 @@ const char* UTIL_getFileExtension(const char* infilename)
    return extension;
 }
 
-/*
- * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
- *                       and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
- * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
- * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
- */
-const char**
-UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
-                    char** allocatedBuffer, unsigned* allocatedNamesNb,
-                    int followLinks)
+
+static FileNamesTable*
+createFNT_fromFNT(FileNamesTable* fnt, int followLinks)
 {
     size_t pos;
-    unsigned i, nbFiles;
+    size_t const nbIfns = fnt->tableSize;
+    unsigned nbFiles;
+    const char** const inputNames = fnt->fileNames;
     char* buf = (char*)malloc(LIST_SIZE_INCREASE);
     char* bufend = buf + LIST_SIZE_INCREASE;
 
     if (!buf) return NULL;
 
-    for (i=0, pos=0, nbFiles=0; i= bufend) {
-                ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;
-                assert(newListSize >= 0);
-                buf = (char*)UTIL_realloc(buf, (size_t)newListSize);
-                bufend = buf + newListSize;
-                if (!buf) return NULL;
-            }
-            if (buf + pos + len < bufend) {
-                memcpy(buf+pos, inputNames[i], len+1);  /* including final \0 */
-                pos += len + 1;
-                nbFiles++;
-            }
-        } else {
-            nbFiles += (unsigned)UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend, followLinks);
-            if (buf == NULL) return NULL;
-    }   }
+    {   size_t ifnNb;
+        for (ifnNb=0, pos=0, nbFiles=0; ifnNb= bufend) {
+                    ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;
+                    assert(newListSize >= 0);
+                    buf = (char*)UTIL_realloc(buf, (size_t)newListSize);
+                    bufend = buf + newListSize;
+                    if (!buf) return NULL;
+                }
+                if (buf + pos + len < bufend) {
+                    memcpy(buf+pos, inputNames[ifnNb], len+1);  /* including final \0 */
+                    pos += len + 1;
+                    nbFiles++;
+                }
+            } else {
+                nbFiles += (unsigned)UTIL_prepareFileList(inputNames[ifnNb], &buf, &pos, &bufend, followLinks);
+                if (buf == NULL) return NULL;
+    }   }   }
 
     if (nbFiles == 0) { free(buf); return NULL; }
 
-    {   const char** const fileTable = (const char**)malloc((nbFiles + 1) * sizeof(*fileTable));
-        if (!fileTable) { free(buf); return NULL; }
+    {   size_t ifnNb;
+        const char** const fileNamesTable = (const char**)malloc((nbFiles + 1) * sizeof(*fileNamesTable));
+        if (!fileNamesTable) { free(buf); return NULL; }
 
-        for (i = 0, pos = 0; i < nbFiles; i++) {
-            fileTable[i] = buf + pos;
-            if (buf + pos > bufend) { free(buf); free((void*)fileTable); return NULL; }
-            pos += strlen(fileTable[i]) + 1;
+        for (ifnNb = 0, pos = 0; ifnNb < nbFiles; ifnNb++) {
+            fileNamesTable[ifnNb] = buf + pos;
+            if (buf + pos > bufend) { free(buf); free((void*)fileNamesTable); return NULL; }
+            pos += strlen(fileNamesTable[ifnNb]) + 1;
         }
 
-        *allocatedBuffer = buf;
-        *allocatedNamesNb = nbFiles;
-
-        return fileTable;
+        return UTIL_createFileNamesTable(fileNamesTable, nbFiles, buf);
     }
 }
 
 
-void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)
+FileNamesTable*
+UTIL_expandFileNamesTable(FileNamesTable* fnt, int followLinks)
 {
-    if (allocatedBuffer) free(allocatedBuffer);
-    if (filenameTable) free((void*)filenameTable);
+    FileNamesTable* const newFNT = createFNT_fromFNT(fnt, followLinks);
+    UTIL_freeFileNamesTable(fnt);
+    return newFNT;
 }
 
 
-
 /*-****************************************
 *  count the number of physical cores
 ******************************************/
diff --git a/programs/util.h b/programs/util.h
index 93780a4fea3..3f154de0da2 100644
--- a/programs/util.h
+++ b/programs/util.h
@@ -159,12 +159,12 @@ U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles);
    /* do not define UTIL_HAS_CREATEFILELIST */
 #endif /* #ifdef _WIN32 */
 
-/*Note: tableSize denotes the total capacity of table*/
 typedef struct
 {
     const char** fileNames;
-    char* buf;
-    size_t tableSize;
+    char* buf;            /* fileNames are stored in this buffer (or are read-only) */
+    size_t tableSize;     /* nb of fileNames */
+    size_t tableCapacity;
 } FileNamesTable;
 
 /*! UTIL_createFileNamesTable_fromFileName() :
@@ -183,7 +183,6 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName);
 FileNamesTable*
 UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf);
 
-
 /*! UTIL_freeFileNamesTable() :
  *  This function is compatible with NULL argument and never fails.
  */
@@ -197,19 +196,31 @@ FileNamesTable*
 UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2);
 
 
-/*
- * UTIL_createFileList() :
- * takes a list of files and directories (@inputNames, @inputNamesNb),
- * scans directories, and returns a new list of files (@return, @allocatedBuffer, @allocatedNamesNb).
- * In case of error, UTIL_createFileList() returns NULL.
- * After list's end of life, the structures should be freed with UTIL_freeFileList (@return, @allocatedBuffer).
+/*! UTIL_expandFileNamesTable() :
+ *  read names from @fnt, expand those corresponding to directories
+ * @return : an expanded FileNamesTable*, with only file names,
+ *        or NULL in case of error.
+ *  Note: the function takes ownership of fnt, and consumes it (free it)
+ */
+FileNamesTable* UTIL_expandFileNamesTable(FileNamesTable* fnt, int followLinks);
+
+
+/*! UTIL_allocateFileNamesTable() :
+ *  Allocates a table of const char*, to insert read-only names later on.
+ *  The created FileNamesTable* doesn't hold a buffer.
+ * @return : FileNamesTable*, or NULL, if allocation fails.
  */
-const char**
-UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
-                    char** allocatedBuffer, unsigned* allocatedNamesNb,
-                    int followLinks);
+FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize);
 
-void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer);
+
+/*! UTIL_refFilename() :
+ *  Add a read-only name to reference into @fnt table.
+ *  Since @filename is only referenced, its lifetime must outlive @fnt.
+ *  This function never fails, but it can abort().
+ *  Internal table must be large enough to reference a new member
+ *  (capacity > size), otherwise the function will abort().
+ */
+void UTIL_refFilename(FileNamesTable* fnt, const char* filename);
 
 
 /*-****************************************
diff --git a/programs/zstdcli.c b/programs/zstdcli.c
index a244b6c4d03..8a9b1fcdbb5 100644
--- a/programs/zstdcli.c
+++ b/programs/zstdcli.c
@@ -585,10 +585,8 @@ int main(int argCount, const char* argv[])
     int cLevelLast = -1000000000;
     unsigned recursive = 0;
     unsigned memLimit = 0;
-    size_t filenameTableSize = argCount;
-    const char** filenameTable = (const char**)malloc(filenameTableSize * sizeof(const char*));   /* argCount >= 1 */
-    char* tableBuf = NULL;
-    unsigned filenameIdx = 0;
+    FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */
+    FileNamesTable* file_of_names = UTIL_allocateFileNamesTable((size_t)argCount);  /* argCount >= 1 */
     const char* programName = argv[0];
     const char* outFileName = NULL;
     const char* outDirName = NULL;
@@ -601,11 +599,6 @@ int main(int argCount, const char* argv[])
     size_t srcSizeHint = 0;
     int dictCLevel = g_defaultDictCLevel;
     unsigned dictSelect = g_defaultSelectivityLevel;
-#ifdef UTIL_HAS_CREATEFILELIST
-    const char** extendedFileList = NULL;
-    char* fileNamesBuf = NULL;
-    unsigned fileNamesNb;
-#endif
 #ifndef ZSTD_NODICT
     ZDICT_cover_params_t coverParams = defaultCoverParams();
     ZDICT_fastCover_params_t fastCoverParams = defaultFastCoverParams();
@@ -620,8 +613,7 @@ int main(int argCount, const char* argv[])
     /* init */
     (void)recursive; (void)cLevelLast;    /* not used when ZSTD_NOBENCH set */
     (void)memLimit;   /* not used when ZSTD_NODECOMPRESS set */
-    if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); }
-    filenameTable[0] = stdinmark;
+    if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAY("zstd: allocation error \n"); exit(1); }
     g_displayOut = stderr;
     cLevel = init_cLevel();
     programName = lastNameFromPath(programName);
@@ -651,363 +643,317 @@ int main(int argCount, const char* argv[])
     /* command switches */
     for (argNb=1; argNb maxFast) fastLevel = maxFast;
+                        if (fastLevel) {
+                          dictCLevel = cLevel = -(int)fastLevel;
                         } else {
-                            cLevel = -1;  /* default for --fast */
+                          CLEAN_RETURN(badusage(programName));
                         }
-                        continue;
+                    } else if (*argument != 0) {
+                        /* Invalid character following --fast */
+                        CLEAN_RETURN(badusage(programName));
+                    } else {
+                        cLevel = -1;  /* default for --fast */
                     }
+                    continue;
+                }
 #endif
 
-                    if (longCommandWArg(&argument, "--filelist=")) {
-                        /* note : in theory, it's better to just store the arguments at this stage,
-                         *    and only start to load & interpret the file after command line is parsed.
-                         *    For a single file, it would be easy to just store its name here, and parse later.
-                         *    However, this implementation makes it possible to read multiple files.
-                         *    An equivalent will have to be able to store multiple file names.
-                         */
-                        FileNamesTable* extendedTable;
-                        FileNamesTable* curTable;
-                        FileNamesTable* concatenatedTables;
-
-                        if (!UTIL_fileExist(argument) || !UTIL_isRegularFile(argument)){
-                            DISPLAYLEVEL(1, "[ERROR] wrong fileName: %s\n", argument);
-                            CLEAN_RETURN(badusage(programName));
-                        }
-
-                        extendedTable = UTIL_createFileNamesTable_fromFileName(argument);
-                        if (!extendedTable) {
-                            CLEAN_RETURN(badusage(programName));
-                        }
-
-
-                        filenameTable[filenameIdx] = NULL;   /* marking end of table */
-                        filenameIdx += (unsigned) extendedTable->tableSize;
-
-                        curTable = UTIL_createFileNamesTable(filenameTable, filenameTableSize, tableBuf);
-
-                        if (!curTable) {
-                            UTIL_freeFileNamesTable(extendedTable);
-                            CLEAN_RETURN(badusage(programName));
-                        }
-
-                        concatenatedTables = UTIL_concatenateTwoTables(curTable, extendedTable);
-                        if (!concatenatedTables) {
-                            UTIL_freeFileNamesTable(curTable);
-                            UTIL_freeFileNamesTable(extendedTable);
-                            CLEAN_RETURN(badusage(programName));
-                        }
+                if (longCommandWArg(&argument, "--filelist=")) {
+                    UTIL_refFilename(file_of_names, argument);
+                    continue;
+                }
 
-                        /* transfer ownership */
-                        filenameTable = concatenatedTables->fileNames;
-                        filenameTableSize = concatenatedTables->tableSize;
-                        tableBuf = concatenatedTables->buf;
-                        concatenatedTables->fileNames = NULL;
-                        concatenatedTables->tableSize = 0;
-                        concatenatedTables->buf = NULL;
-                        UTIL_freeFileNamesTable(concatenatedTables);
+                /* fall-through, will trigger bad_usage() later on */
+            }
 
-                        continue;
-                    }
-                    /* fall-through, will trigger bad_usage() later on */
+            argument++;
+            while (argument[0]!=0) {
+                if (lastCommand) {
+                    DISPLAY("error : command must be followed by argument \n");
+                    CLEAN_RETURN(1);
                 }
-
-                argument++;
-                while (argument[0]!=0) {
-                    if (lastCommand) {
-                        DISPLAY("error : command must be followed by argument \n");
-                        CLEAN_RETURN(1);
-                    }
 #ifndef ZSTD_NOCOMPRESS
-                    /* compression Level */
-                    if ((*argument>='0') && (*argument<='9')) {
-                        dictCLevel = cLevel = (int)readU32FromChar(&argument);
-                        continue;
-                    }
+                /* compression Level */
+                if ((*argument>='0') && (*argument<='9')) {
+                    dictCLevel = cLevel = (int)readU32FromChar(&argument);
+                    continue;
+                }
 #endif
 
-                    switch(argument[0])
-                    {
-                        /* Display help */
-                    case 'V': g_displayOut=stdout; printVersion(); CLEAN_RETURN(0);   /* Version Only */
-                    case 'H':
-                    case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
+                switch(argument[0])
+                {
+                    /* Display help */
+                case 'V': g_displayOut=stdout; printVersion(); CLEAN_RETURN(0);   /* Version Only */
+                case 'H':
+                case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
 
-                         /* Compress */
-                    case 'z': operation=zom_compress; argument++; break;
+                     /* Compress */
+                case 'z': operation=zom_compress; argument++; break;
 
-                         /* Decoding */
-                    case 'd':
+                     /* Decoding */
+                case 'd':
 #ifndef ZSTD_NOBENCH
-                            benchParams.mode = BMK_decodeOnly;
-                            if (operation==zom_bench) { argument++; break; }  /* benchmark decode (hidden option) */
+                        benchParams.mode = BMK_decodeOnly;
+                        if (operation==zom_bench) { argument++; break; }  /* benchmark decode (hidden option) */
 #endif
-                            operation=zom_decompress; argument++; break;
+                        operation=zom_decompress; argument++; break;
 
-                        /* Force stdout, even if stdout==console */
-                    case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
+                    /* Force stdout, even if stdout==console */
+                case 'c': forceStdout=1; outFileName=stdoutmark; argument++; break;
 
-                        /* Use file content as dictionary */
-                    case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
+                    /* Use file content as dictionary */
+                case 'D': nextEntryIsDictionary = 1; lastCommand = 1; argument++; break;
 
-                        /* Overwrite */
-                    case 'f': FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; argument++; break;
+                    /* Overwrite */
+                case 'f': FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; argument++; break;
 
-                        /* Verbose mode */
-                    case 'v': g_displayLevel++; argument++; break;
+                    /* Verbose mode */
+                case 'v': g_displayLevel++; argument++; break;
 
-                        /* Quiet mode */
-                    case 'q': g_displayLevel--; argument++; break;
+                    /* Quiet mode */
+                case 'q': g_displayLevel--; argument++; break;
 
-                        /* keep source file (default) */
-                    case 'k': FIO_setRemoveSrcFile(prefs, 0); argument++; break;
+                    /* keep source file (default) */
+                case 'k': FIO_setRemoveSrcFile(prefs, 0); argument++; break;
 
-                        /* Checksum */
-                    case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;
+                    /* Checksum */
+                case 'C': FIO_setChecksumFlag(prefs, 2); argument++; break;
 
-                        /* test compressed file */
-                    case 't': operation=zom_test; argument++; break;
+                    /* test compressed file */
+                case 't': operation=zom_test; argument++; break;
 
-                        /* destination file name */
-                    case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
+                    /* destination file name */
+                case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
 
-                        /* limit decompression memory */
-                    case 'M':
-                        argument++;
-                        memLimit = readU32FromChar(&argument);
-                        break;
-                    case 'l': operation=zom_list; argument++; break;
+                    /* limit decompression memory */
+                case 'M':
+                    argument++;
+                    memLimit = readU32FromChar(&argument);
+                    break;
+                case 'l': operation=zom_list; argument++; break;
 #ifdef UTIL_HAS_CREATEFILELIST
-                        /* recursive */
-                    case 'r': recursive=1; argument++; break;
+                    /* recursive */
+                case 'r': recursive=1; argument++; break;
 #endif
 
 #ifndef ZSTD_NOBENCH
-                        /* Benchmark */
-                    case 'b':
-                        operation=zom_bench;
-                        argument++;
-                        break;
-
-                        /* range bench (benchmark only) */
-                    case 'e':
-                        /* compression Level */
-                        argument++;
-                        cLevelLast = (int)readU32FromChar(&argument);
-                        break;
-
-                        /* Modify Nb Iterations (benchmark only) */
-                    case 'i':
-                        argument++;
-                        bench_nbSeconds = readU32FromChar(&argument);
-                        break;
-
-                        /* cut input into blocks (benchmark only) */
-                    case 'B':
-                        argument++;
-                        blockSize = readU32FromChar(&argument);
-                        break;
-
-                        /* benchmark files separately (hidden option) */
-                    case 'S':
-                        argument++;
-                        separateFiles = 1;
-                        break;
+                    /* Benchmark */
+                case 'b':
+                    operation=zom_bench;
+                    argument++;
+                    break;
+
+                    /* range bench (benchmark only) */
+                case 'e':
+                    /* compression Level */
+                    argument++;
+                    cLevelLast = (int)readU32FromChar(&argument);
+                    break;
+
+                    /* Modify Nb Iterations (benchmark only) */
+                case 'i':
+                    argument++;
+                    bench_nbSeconds = readU32FromChar(&argument);
+                    break;
+
+                    /* cut input into blocks (benchmark only) */
+                case 'B':
+                    argument++;
+                    blockSize = readU32FromChar(&argument);
+                    break;
+
+                    /* benchmark files separately (hidden option) */
+                case 'S':
+                    argument++;
+                    separateFiles = 1;
+                    break;
 
 #endif   /* ZSTD_NOBENCH */
 
-                        /* nb of threads (hidden option) */
-                    case 'T':
-                        argument++;
-                        nbWorkers = (int)readU32FromChar(&argument);
-                        break;
+                    /* nb of threads (hidden option) */
+                case 'T':
+                    argument++;
+                    nbWorkers = (int)readU32FromChar(&argument);
+                    break;
 
-                        /* Dictionary Selection level */
-                    case 's':
-                        argument++;
-                        dictSelect = readU32FromChar(&argument);
-                        break;
+                    /* Dictionary Selection level */
+                case 's':
+                    argument++;
+                    dictSelect = readU32FromChar(&argument);
+                    break;
 
-                        /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
-                    case 'p': argument++;
+                    /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
+                case 'p': argument++;
 #ifndef ZSTD_NOBENCH
-                        if ((*argument>='0') && (*argument<='9')) {
-                            benchParams.additionalParam = (int)readU32FromChar(&argument);
-                        } else
+                    if ((*argument>='0') && (*argument<='9')) {
+                        benchParams.additionalParam = (int)readU32FromChar(&argument);
+                    } else
 #endif
-                            main_pause=1;
-                        break;
-
-                        /* Select compressibility of synthetic sample */
-                    case 'P':
-                    {   argument++;
-                        compressibility = (double)readU32FromChar(&argument) / 100;
-                    }
+                        main_pause=1;
                     break;
 
-                        /* unknown command */
-                    default : CLEAN_RETURN(badusage(programName));
-                    }
+                    /* Select compressibility of synthetic sample */
+                case 'P':
+                {   argument++;
+                    compressibility = (double)readU32FromChar(&argument) / 100;
                 }
-                continue;
-            }   /* if (argument[0]=='-') */
-
-            if (nextArgumentIsMaxDict) {  /* kept available for compatibility with old syntax ; will be removed one day */
-                nextArgumentIsMaxDict = 0;
-                lastCommand = 0;
-                maxDictSize = readU32FromChar(&argument);
-                continue;
-            }
+                break;
 
-            if (nextArgumentIsDictID) {  /* kept available for compatibility with old syntax ; will be removed one day */
-                nextArgumentIsDictID = 0;
-                lastCommand = 0;
-                dictID = readU32FromChar(&argument);
-                continue;
+                    /* unknown command */
+                default : CLEAN_RETURN(badusage(programName));
+                }
             }
+            continue;
+        }   /* if (argument[0]=='-') */
+
+        if (nextArgumentIsMaxDict) {  /* kept available for compatibility with old syntax ; will be removed one day */
+            nextArgumentIsMaxDict = 0;
+            lastCommand = 0;
+            maxDictSize = readU32FromChar(&argument);
+            continue;
+        }
 
-        }   /* if (nextArgumentIsAFile==0) */
+        if (nextArgumentIsDictID) {  /* kept available for compatibility with old syntax ; will be removed one day */
+            nextArgumentIsDictID = 0;
+            lastCommand = 0;
+            dictID = readU32FromChar(&argument);
+            continue;
+        }
 
         if (nextEntryIsDictionary) {
             nextEntryIsDictionary = 0;
@@ -1031,8 +977,8 @@ int main(int argCount, const char* argv[])
             continue;
         }
 
-        /* add filename to list */
-        filenameTable[filenameIdx++] = argument;
+        /* none of the above : add filename to list */
+        UTIL_refFilename(filenames, argument);
     }
 
     if (lastCommand) { /* forgotten argument */
@@ -1056,37 +1002,47 @@ int main(int argCount, const char* argv[])
 #ifdef UTIL_HAS_CREATEFILELIST
     g_utilDisplayLevel = g_displayLevel;
     if (!followLinks) {
-        unsigned u;
-        for (u=0, fileNamesNb=0; utableSize;
+        for (u=0, fileNamesNb=0; ufileNames[u])
 #ifndef _MSC_VER
-                && !UTIL_isFIFO(filenameTable[u])
+                && !UTIL_isFIFO(filenames->fileNames[u])
 #endif /* _MSC_VER */
             ) {
-                DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", filenameTable[u]);
+                DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", filenames->fileNames[u]);
             } else {
-                filenameTable[fileNamesNb++] = filenameTable[u];
+                filenames->fileNames[fileNamesNb++] = filenames->fileNames[u];
         }   }
-        if (fileNamesNb == 0 && filenameIdx > 0)
+        if (fileNamesNb == 0 && nbFilenames > 0)  /* all names are eliminated */
             CLEAN_RETURN(1);
-        filenameIdx = fileNamesNb;
+        filenames->tableSize = fileNamesNb;
+    }   /* if (!followLinks) */
+
+    /* read names from a file */
+    if (file_of_names->tableSize) {
+        size_t const nbFileLists = file_of_names->tableSize;
+        size_t flNb;
+        for (flNb=0; flNb < nbFileLists; flNb++) {
+            FileNamesTable* const fnt = UTIL_createFileNamesTable_fromFileName(file_of_names->fileNames[flNb]);
+            if (fnt==NULL) {
+                DISPLAYLEVEL(1, "zstd: error reading %s \n", file_of_names->fileNames[flNb]);
+                CLEAN_RETURN(1);
+            }
+            filenames = UTIL_concatenateTwoTables(filenames, fnt);
+        }
     }
+
     if (recursive) {  /* at this stage, filenameTable is a list of paths, which can contain both files and directories */
-        extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb, followLinks);
-        if (extendedFileList) {
-            unsigned u;
-            for (u=0; utableSize, filenames->fileNames, g_displayLevel);
         CLEAN_RETURN(ret);
 #else
         DISPLAY("file information is not supported \n");
@@ -1117,18 +1073,18 @@ int main(int argCount, const char* argv[])
         if (cLevelLast < cLevel) cLevelLast = cLevel;
         if (cLevelLast > cLevel)
             DISPLAYLEVEL(3, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast);
-        if (filenameIdx) {
+        if (filenames->tableSize > 0) {
             if(separateFiles) {
                 unsigned i;
-                for(i = 0; i < filenameIdx; i++) {
+                for(i = 0; i < filenames->tableSize; i++) {
                     int c;
-                    DISPLAYLEVEL(3, "Benchmarking %s \n", filenameTable[i]);
+                    DISPLAYLEVEL(3, "Benchmarking %s \n", filenames->fileNames[i]);
                     for(c = cLevel; c <= cLevelLast; c++) {
-                        BMK_benchFilesAdvanced(&filenameTable[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams);
+                        BMK_benchFilesAdvanced(&filenames->fileNames[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams);
                 }   }
             } else {
                 for(; cLevel <= cLevelLast; cLevel++) {
-                    BMK_benchFilesAdvanced(filenameTable, filenameIdx, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams);
+                    BMK_benchFilesAdvanced(filenames->fileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams);
             }   }
         } else {
             for(; cLevel <= cLevelLast; cLevel++) {
@@ -1152,18 +1108,18 @@ int main(int argCount, const char* argv[])
             int const optimize = !coverParams.k || !coverParams.d;
             coverParams.nbThreads = (unsigned)nbWorkers;
             coverParams.zParams = zParams;
-            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, blockSize, NULL, &coverParams, NULL, optimize);
+            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, NULL, &coverParams, NULL, optimize);
         } else if (dict == fastCover) {
             int const optimize = !fastCoverParams.k || !fastCoverParams.d;
             fastCoverParams.nbThreads = (unsigned)nbWorkers;
             fastCoverParams.zParams = zParams;
-            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, blockSize, NULL, NULL, &fastCoverParams, optimize);
+            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, NULL, NULL, &fastCoverParams, optimize);
         } else {
             ZDICT_legacy_params_t dictParams;
             memset(&dictParams, 0, sizeof(dictParams));
             dictParams.selectivityLevel = dictSelect;
             dictParams.zParams = zParams;
-            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenameTable, filenameIdx, blockSize, &dictParams, NULL, NULL, 0);
+            operationResult = DiB_trainFromFiles(outFileName, maxDictSize, filenames->fileNames, (unsigned)filenames->tableSize, blockSize, &dictParams, NULL, NULL, 0);
         }
 #else
         (void)dictCLevel; (void)dictSelect; (void)dictID;  (void)maxDictSize; /* not used when ZSTD_NODICT set */
@@ -1178,16 +1134,16 @@ int main(int argCount, const char* argv[])
 #endif
 
     /* No input filename ==> use stdin and stdout */
-    filenameIdx += !filenameIdx;   /* filenameTable[0] is stdin by default */
-    if (!strcmp(filenameTable[0], stdinmark) && !outFileName)
+    if (filenames->tableSize == 0) UTIL_refFilename(filenames, stdinmark);
+    if (!strcmp(filenames->fileNames[0], stdinmark) && !outFileName)
         outFileName = stdoutmark;  /* when input is stdin, default output is stdout */
 
     /* Check if input/output defined as console; trigger an error in this case */
-    if (!strcmp(filenameTable[0], stdinmark) && IS_CONSOLE(stdin) )
+    if (!strcmp(filenames->fileNames[0], stdinmark) && IS_CONSOLE(stdin) )
         CLEAN_RETURN(badusage(programName));
     if ( outFileName && !strcmp(outFileName, stdoutmark)
       && IS_CONSOLE(stdout)
-      && !strcmp(filenameTable[0], stdinmark)
+      && !strcmp(filenames->fileNames[0], stdinmark)
       && !forceStdout
       && operation!=zom_decompress )
         CLEAN_RETURN(badusage(programName));
@@ -1202,8 +1158,8 @@ int main(int argCount, const char* argv[])
 #endif
 
     /* No status message in pipe mode (stdin - stdout) or multi-files mode */
-    if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1;
-    if ((filenameIdx>1) & (g_displayLevel==2)) g_displayLevel=1;
+    if (!strcmp(filenames->fileNames[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1;
+    if ((filenames->tableSize > 1) & (g_displayLevel==2)) g_displayLevel=1;
 
     /* IO Stream/File */
     FIO_setNotificationLevel(g_displayLevel);
@@ -1228,10 +1184,10 @@ int main(int argCount, const char* argv[])
         if (adaptMin > cLevel) cLevel = adaptMin;
         if (adaptMax < cLevel) cLevel = adaptMax;
 
-        if ((filenameIdx==1) && outFileName)
-          operationResult = FIO_compressFilename(prefs, outFileName, filenameTable[0], dictFileName, cLevel, compressionParams);
+        if ((filenames->tableSize==1) && outFileName)
+          operationResult = FIO_compressFilename(prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams);
         else
-          operationResult = FIO_compressMultipleFilenames(prefs, filenameTable, filenameIdx, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams);
+          operationResult = FIO_compressMultipleFilenames(prefs, filenames->fileNames, (unsigned)filenames->tableSize, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams);
 #else
         (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; /* not used when ZSTD_NOCOMPRESS set */
         DISPLAY("Compression not supported \n");
@@ -1246,10 +1202,10 @@ int main(int argCount, const char* argv[])
             }
         }
         FIO_setMemLimit(prefs, memLimit);
-        if (filenameIdx==1 && outFileName) {
-            operationResult = FIO_decompressFilename(prefs, outFileName, filenameTable[0], dictFileName);
+        if (filenames->tableSize == 1 && outFileName) {
+            operationResult = FIO_decompressFilename(prefs, outFileName, filenames->fileNames[0], dictFileName);
         } else {
-            operationResult = FIO_decompressMultipleFilenames(prefs, filenameTable, filenameIdx, outDirName, outFileName, dictFileName);
+            operationResult = FIO_decompressMultipleFilenames(prefs, filenames->fileNames, (unsigned)filenames->tableSize, outDirName, outFileName, dictFileName);
         }
 #else
         DISPLAY("Decompression not supported \n");
@@ -1258,16 +1214,9 @@ int main(int argCount, const char* argv[])
 
 _end:
     FIO_freePreferences(prefs);
-
-    free(tableBuf);
-
     if (main_pause) waitEnter();
-#ifdef UTIL_HAS_CREATEFILELIST
-    if (extendedFileList)
-        UTIL_freeFileList(extendedFileList, fileNamesBuf);
-    else
-#endif
-    free((void*)filenameTable);
+    UTIL_freeFileNamesTable(filenames);
+    UTIL_freeFileNamesTable(file_of_names);
 
     return operationResult;
 }

From 7977899538409b62a4d132e767d8bf4ad0dbaff8 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Tue, 5 Nov 2019 17:25:20 -0800
Subject: [PATCH 039/402] updated zwrapbench to use FileNamesTable* abstraction

---
 zlibWrapper/examples/zwrapbench.c | 42 +++++++++----------------------
 1 file changed, 12 insertions(+), 30 deletions(-)

diff --git a/zlibWrapper/examples/zwrapbench.c b/zlibWrapper/examples/zwrapbench.c
index 35893a4b438..38d19ed1f53 100644
--- a/zlibWrapper/examples/zwrapbench.c
+++ b/zlibWrapper/examples/zwrapbench.c
@@ -74,7 +74,7 @@ static U32 g_compressibilityDefault = 50;
 #define DEFAULT_DISPLAY_LEVEL 2
 #define DISPLAY(...)         fprintf(displayOut, __VA_ARGS__)
 #define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
-static int g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
+static unsigned g_displayLevel = DEFAULT_DISPLAY_LEVEL;   /* 0 : no display;   1: errors;   2 : + result + interaction + warnings;   3 : + progression;   4 : + information */
 static FILE* displayOut;
 
 #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
@@ -848,7 +848,7 @@ static unsigned readU32FromChar(const char** stringPtr)
 {
     unsigned result = 0;
     while ((**stringPtr >='0') && (**stringPtr <='9'))
-        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
+        result *= 10, result += (unsigned)(**stringPtr - '0'), (*stringPtr)++ ;
     return result;
 }
 
@@ -865,24 +865,18 @@ int main(int argCount, char** argv)
     int cLevel = ZSTDCLI_CLEVEL_DEFAULT;
     int cLevelLast = 1;
     unsigned recursive = 0;
-    const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*));   /* argCount >= 1 */
-    unsigned filenameIdx = 0;
+    FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount);
     const char* programName = argv[0];
     const char* dictFileName = NULL;
     char* dynNameSpace = NULL;
-#ifdef UTIL_HAS_CREATEFILELIST
-    const char** fileNamesTable = NULL;
-    char* fileNamesBuf = NULL;
-    unsigned fileNamesNb;
-#endif
 
     /* init */
-    if (filenameTable==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); }
+    if (filenames==NULL) { DISPLAY("zstd: %s \n", strerror(errno)); exit(1); }
     displayOut = stderr;
 
     /* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
     {   size_t pos;
-        for (pos = (int)strlen(programName); pos > 0; pos--) { if (programName[pos] == '/') { pos++; break; } }
+        for (pos = strlen(programName); pos > 0; pos--) { if (programName[pos] == '/') { pos++; break; } }
         programName += pos;
     }
 
@@ -930,14 +924,14 @@ int main(int argCount, char** argv)
                     case 'b':
                             /* first compression Level */
                             argument++;
-                            cLevel = readU32FromChar(&argument);
+                            cLevel = (int)readU32FromChar(&argument);
                             break;
 
                         /* range bench (benchmark only) */
                     case 'e':
                             /* last compression Level */
                             argument++;
-                            cLevelLast = readU32FromChar(&argument);
+                            cLevelLast = (int)readU32FromChar(&argument);
                             break;
 
                         /* Modify Nb Iterations (benchmark only) */
@@ -964,7 +958,7 @@ int main(int argCount, char** argv)
                         /* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
                     case 'p': argument++;
                         if ((*argument>='0') && (*argument<='9')) {
-                            BMK_setAdditionalParam(readU32FromChar(&argument));
+                            BMK_setAdditionalParam((int)readU32FromChar(&argument));
                         } else
                             main_pause=1;
                         break;
@@ -984,7 +978,7 @@ int main(int argCount, char** argv)
         }
 
         /* add filename to list */
-        filenameTable[filenameIdx++] = argument;
+        UTIL_refFilename(filenames, argument);
     }
 
     /* Welcome message (if verbose) */
@@ -992,28 +986,16 @@ int main(int argCount, char** argv)
 
 #ifdef UTIL_HAS_CREATEFILELIST
     if (recursive) {
-        fileNamesTable = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, &fileNamesNb, 1);
-        if (fileNamesTable) {
-            unsigned u;
-            for (u=0; ufileNames, (unsigned)filenames->tableSize, dictFileName, cLevel, cLevelLast);
 
 _end:
     if (main_pause) waitEnter();
     free(dynNameSpace);
-#ifdef UTIL_HAS_CREATEFILELIST
-    if (fileNamesTable)
-        UTIL_freeFileList(fileNamesTable, fileNamesBuf);
-    else
-#endif
-        free((void*)filenameTable);
+    UTIL_freeFileNamesTable(filenames);
     return operationResult;
 }

From 66b6688274a37c3c1911b9848e955ea25463af73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Ketelaars?= 
Date: Wed, 6 Nov 2019 11:39:59 +0100
Subject: [PATCH 040/402] 'head -c BYTES' is non-portable.

Similar to #1321: The '-c' option for 'head' is non-portable (not in
POSIX).
---
 tests/playTests.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/playTests.sh b/tests/playTests.sh
index c09e0c21cc2..124500b453d 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -274,7 +274,7 @@ test -f tmp.zst  # destination file should still be present
 rm -rf tmp*  # may also erase tmp* directory from previous failed run
 
 println "\n===> decompression only tests "
-head -c 1048576 /dev/zero > tmp
+dd bs=1 count=1048576 if=/dev/zero of=tmp
 $ZSTD -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst"
 $DIFF -s tmp1 tmp
 rm tmp*
@@ -1173,9 +1173,9 @@ rm -f tmp* dictionary
 if [ "$isWindows" = false ] ; then
 
 println "\n===>  zstd fifo named pipe test "
-head -c 10 /dev/zero > tmp_original
+dd bs=1 count=10 if=/dev/zero of=tmp_original
 mkfifo named_pipe
-head -c 10 /dev/zero > named_pipe &
+dd bs=1 count=10 if=/dev/zero of=named_pipe &
 $ZSTD named_pipe -o tmp_compressed
 $ZSTD -d -o tmp_decompressed tmp_compressed
 $DIFF -s tmp_original tmp_decompressed

From e488cabf25955f9d55e99e879429e408f7939114 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Ketelaars?= 
Date: Wed, 6 Nov 2019 12:16:02 +0100
Subject: [PATCH 041/402] 'date -r FILE' is non-portable.

date(1) is used to display the last modification time of a file, which
is not supported on OpenBSD, FreeBSD and Darwin. Instead use stat(1).

Tested on OpenBSD.
---
 tests/playTests.sh | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tests/playTests.sh b/tests/playTests.sh
index c09e0c21cc2..7c18351a792 100755
--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -92,6 +92,11 @@ case "$UNAME" in
   *) MD5SUM="md5sum" ;;
 esac
 
+MTIME="stat -c %Y"
+case "$UNAME" in
+    Darwin | FreeBSD | OpenBSD) MTIME="stat -f %m" ;;
+esac
+
 DIFF="diff"
 case "$UNAME" in
   SunOS) DIFF="gdiff" ;;
@@ -227,8 +232,8 @@ sleep 5
 $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir
 test ! -f precompressedFilterTestDir/input.5.zst.zst
 test ! -f precompressedFilterTestDir/input.6.zst.zst
-file1timestamp=`date -r precompressedFilterTestDir/input.5.zst +%s`
-file2timestamp=`date -r precompressedFilterTestDir/input.7.zst +%s`
+file1timestamp=`$MTIME precompressedFilterTestDir/input.5.zst`
+file2timestamp=`$MTIME precompressedFilterTestDir/input.7.zst`
 if [[ $file2timestamp -ge $file1timestamp ]]; then
   println "Test is successful. input.5.zst is precompressed and therefore not compressed/modified again."
 else

From 31a0abbfda9c7264480922811030073f4dcaa8b5 Mon Sep 17 00:00:00 2001
From: Yann Collet 
Date: Wed, 6 Nov 2019 09:10:05 -0800
Subject: [PATCH 042/402] updated pzstd and largeNbDicts to use the new
 FileNamesTable* abstraction

---
 contrib/largeNbDicts/largeNbDicts.c | 33 +++++++++++++++--------------
 contrib/pzstd/Options.cpp           | 14 +++++-------
 doc/zstd_manual.html                |  6 ------
 programs/util.c                     | 17 ++++++---------
 programs/util.h                     | 23 +++++++++++++-------
 programs/zstdcli.c                  |  4 ++--
 zlibWrapper/examples/zwrapbench.c   |  2 +-
 7 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/contrib/largeNbDicts/largeNbDicts.c b/contrib/largeNbDicts/largeNbDicts.c
index 627a6910576..0038e2041f6 100644
--- a/contrib/largeNbDicts/largeNbDicts.c
+++ b/contrib/largeNbDicts/largeNbDicts.c
@@ -429,14 +429,14 @@ void shuffleDictionaries(ddict_collection_t dicts)
 {
     size_t const nbDicts = dicts.nbDDict;
     for (size_t r=0; r='0') && (**stringPtr <='9')) {
         unsigned const max = (((unsigned)(-1)) / 10) - 1;
         assert(result <= max);   /* check overflow */
-        result *= 10, result += **stringPtr - '0', (*stringPtr)++ ;
+        result *= 10, result += (unsigned)**stringPtr - '0', (*stringPtr)++ ;
     }
     if ((**stringPtr=='K') || (**stringPtr=='M')) {
         unsigned const maxK = ((unsigned)(-1)) >> 10;
@@ -729,7 +729,7 @@ static unsigned readU32FromChar(const char** stringPtr)
  *  If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand.
  * @return 0 and doesn't modify *stringPtr otherwise.
  */
-static unsigned longCommandWArg(const char** stringPtr, const char* longCommand)
+static int longCommandWArg(const char** stringPtr, const char* longCommand)
 {
     size_t const comSize = strlen(longCommand);
     int const result = !strncmp(*stringPtr, longCommand, comSize);
@@ -765,7 +765,7 @@ int bad_usage(const char* exeName)
 int main (int argc, const char** argv)
 {
     int recursiveMode = 0;
-    int nbRounds = BENCH_TIME_DEFAULT_S;
+    unsigned nbRounds = BENCH_TIME_DEFAULT_S;
     const char* const exeName = argv[0];
 
     if (argc < 2) return bad_usage(exeName);
@@ -791,26 +791,27 @@ int main (int argc, const char** argv)
         if (longCommandWArg(&argument, "--blockSize=")) { blockSize = readU32FromChar(&argument); continue; }
         if (longCommandWArg(&argument, "--nbDicts=")) { nbDicts = readU32FromChar(&argument); continue; }
         if (longCommandWArg(&argument, "--nbBlocks=")) { nbBlocks = readU32FromChar(&argument); continue; }
-        if (longCommandWArg(&argument, "--clevel=")) { cLevel = readU32FromChar(&argument); continue; }
-        if (longCommandWArg(&argument, "-")) { cLevel = readU32FromChar(&argument); continue; }
+        if (longCommandWArg(&argument, "--clevel=")) { cLevel = (int)readU32FromChar(&argument); continue; }
+        if (longCommandWArg(&argument, "-")) { cLevel = (int)readU32FromChar(&argument); continue; }
         /* anything that's not a command is a filename */
         nameTable[nameIdx++] = argument;
     }
 
-    const char** filenameTable = nameTable;
-    unsigned nbFiles = nameIdx;
-    char* buffer_containing_filenames = NULL;
+    FileNamesTable* filenameTable;
 
     if (recursiveMode) {
 #ifndef UTIL_HAS_CREATEFILELIST
         assert(0);   /* missing capability, do not run */
 #endif
-        filenameTable = UTIL_createFileList(nameTable, nameIdx, &buffer_containing_filenames, &nbFiles, 1 /* follow_links */);
+        filenameTable = UTIL_createExpandedFNT(nameTable, nameIdx, 1 /* follow_links */);
+    } else {
+        filenameTable = UTIL_createFileNamesTable(nameTable, nameIdx, NULL);
+        nameTable = NULL;  /* UTIL_createFileNamesTable() takes ownership of nameTable */
     }
 
-    int result = bench(filenameTable, nbFiles, dictionary, blockSize, cLevel, nbDicts, nbBlocks, nbRounds);
+    int result = bench(filenameTable->fileNames, (unsigned)filenameTable->tableSize, dictionary, blockSize, cLevel, nbDicts, nbBlocks, nbRounds);
 
-    free(buffer_containing_filenames);
+    UTIL_freeFileNamesTable(filenameTable);
     free(nameTable);
 
     return result;
diff --git a/contrib/pzstd/Options.cpp b/contrib/pzstd/Options.cpp
index 2123f8894c3..37292221b9f 100644
--- a/contrib/pzstd/Options.cpp
+++ b/contrib/pzstd/Options.cpp
@@ -337,23 +337,19 @@ Options::Status Options::parse(int argc, const char **argv) {
 
   // Translate input files/directories into files to (de)compress
   if (recursive) {
-    char *scratchBuffer = nullptr;
-    unsigned numFiles = 0;
-    const char **files =
-        UTIL_createFileList(localInputFiles.data(), localInputFiles.size(),
-                            &scratchBuffer, &numFiles, followLinks);
+    FileNamesTable* const files = UTIL_createExpandedFNT(localInputFiles.data(), localInputFiles.size(), followLinks);
     if (files == nullptr) {
       std::fprintf(stderr, "Error traversing directories\n");
       return Status::Failure;
     }
     auto guard =
-        makeScopeGuard([&] { UTIL_freeFileList(files, scratchBuffer); });
-    if (numFiles == 0) {
+        makeScopeGuard([&] { UTIL_freeFileNamesTable(files); });
+    if (files->tableSize == 0) {
       std::fprintf(stderr, "No files found\n");
       return Status::Failure;
     }
-    inputFiles.resize(numFiles);
-    std::copy(files, files + numFiles, inputFiles.begin());
+    inputFiles.resize(files->tableSize);
+    std::copy(files->fileNames, files->fileNames + files->tableSize, inputFiles.begin());
   } else {
     inputFiles.resize(localInputFiles.size());
     std::copy(localInputFiles.begin(), localInputFiles.end(),
diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
index 7fa1a8d1939..43c5555b8ca 100644
--- a/doc/zstd_manual.html
+++ b/doc/zstd_manual.html
@@ -967,12 +967,6 @@ 

Streaming decompression functions


* tables. However, this model incurs no start-up cost (as long as the * working context's tables can be reused). For small inputs, this can be * faster than copying the CDict's tables. - * - * - The CDict's tables are not used at all, and instead we use the working - * context alone to reload the dictionary and use params based on the source - * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). - * This method is effective when the dictionary sizes are very small relative - * to the input size, and the input size is fairly large to begin with. * * - The CDict's tables are not used at all, and instead we use the working * context alone to reload the dictionary and use params based on the source diff --git a/programs/util.c b/programs/util.c index 55ca5a68127..dae26badb6a 100644 --- a/programs/util.c +++ b/programs/util.c @@ -374,7 +374,7 @@ static size_t getTotalTableSize(FileNamesTable* table) } FileNamesTable* -UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2) +UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2) { unsigned newTableIdx = 0; size_t pos = 0; @@ -587,13 +587,11 @@ const char* UTIL_getFileExtension(const char* infilename) } -static FileNamesTable* -createFNT_fromFNT(FileNamesTable* fnt, int followLinks) +FileNamesTable* +UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) { size_t pos; - size_t const nbIfns = fnt->tableSize; unsigned nbFiles; - const char** const inputNames = fnt->fileNames; char* buf = (char*)malloc(LIST_SIZE_INCREASE); char* bufend = buf + LIST_SIZE_INCREASE; @@ -637,12 +635,11 @@ createFNT_fromFNT(FileNamesTable* fnt, int followLinks) } -FileNamesTable* -UTIL_expandFileNamesTable(FileNamesTable* fnt, int followLinks) +void UTIL_expandFNT(FileNamesTable** fnt, int followLinks) { - FileNamesTable* const newFNT = createFNT_fromFNT(fnt, followLinks); - UTIL_freeFileNamesTable(fnt); - return newFNT; + FileNamesTable* const newFNT = UTIL_createExpandedFNT((*fnt)->fileNames, (*fnt)->tableSize, followLinks); + UTIL_freeFileNamesTable(*fnt); + *fnt = newFNT; } diff --git a/programs/util.h b/programs/util.h index 3f154de0da2..6808c4e3dd2 100644 --- a/programs/util.h +++ b/programs/util.h @@ -188,21 +188,28 @@ UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf); */ void UTIL_freeFileNamesTable(FileNamesTable* table); -/*! UTIL_concatenateTwoTables(): +/*! UTIL_mergeFileNamesTable(): * @return : FileNamesTable*, concatenation of @table1 and @table2 * note: @table1 and @table2 are consumed (freed) by this operation */ FileNamesTable* -UTIL_concatenateTwoTables(FileNamesTable* table1, FileNamesTable* table2); +UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2); -/*! UTIL_expandFileNamesTable() : - * read names from @fnt, expand those corresponding to directories - * @return : an expanded FileNamesTable*, with only file names, - * or NULL in case of error. - * Note: the function takes ownership of fnt, and consumes it (free it) +/*! UTIL_expandFNT() : + * read names from @fnt, and expand those corresponding to directories + * update @fnt, now containing only file names, + * @return : 0 in case of success, 1 if error + * note : in case of error, @fnt[0] is NULL */ -FileNamesTable* UTIL_expandFileNamesTable(FileNamesTable* fnt, int followLinks); +void UTIL_expandFNT(FileNamesTable** fnt, int followLinks); + +/*! UTIL_createExpandedFNT() : + * read names from @filenames, and expand those corresponding to directories + * @return : an expanded FileNamesTable*, where each name is a file + * or NULL in case of error + */ +FileNamesTable* UTIL_createExpandedFNT(const char** filenames, size_t nbFilenames, int followLinks); /*! UTIL_allocateFileNamesTable() : diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 8a9b1fcdbb5..57dbaa82122 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1029,12 +1029,12 @@ int main(int argCount, const char* argv[]) DISPLAYLEVEL(1, "zstd: error reading %s \n", file_of_names->fileNames[flNb]); CLEAN_RETURN(1); } - filenames = UTIL_concatenateTwoTables(filenames, fnt); + filenames = UTIL_mergeFileNamesTable(filenames, fnt); } } if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */ - filenames = UTIL_expandFileNamesTable(filenames, followLinks); + UTIL_expandFNT(&filenames, followLinks); } #else (void)followLinks; diff --git a/zlibWrapper/examples/zwrapbench.c b/zlibWrapper/examples/zwrapbench.c index 38d19ed1f53..f30cad40c71 100644 --- a/zlibWrapper/examples/zwrapbench.c +++ b/zlibWrapper/examples/zwrapbench.c @@ -986,7 +986,7 @@ int main(int argCount, char** argv) #ifdef UTIL_HAS_CREATEFILELIST if (recursive) { - filenames = UTIL_expandFileNamesTable(filenames, 1); + UTIL_expandFNT(&filenames, 1); } #endif From c13f81905a3241dcef5ec9273eb5dfb326e83beb Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 6 Nov 2019 16:05:02 -0500 Subject: [PATCH 043/402] Fix #1861: Restrict overlapLog Parameter When Not Built With Multithreading This parameter is unused in single-threaded compression. We should make it behave like the other multithread-only parameters, for which we only accept zero when we are not built with multithreading. --- lib/compress/zstd_compress.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 35346b92cb1..edeac4b9502 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -339,8 +339,13 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) return bounds; case ZSTD_c_overlapLog: +#ifdef ZSTD_MULTITHREAD bounds.lowerBound = ZSTD_OVERLAPLOG_MIN; bounds.upperBound = ZSTD_OVERLAPLOG_MAX; +#else + bounds.lowerBound = 0; + bounds.upperBound = 0; +#endif return bounds; case ZSTD_c_enableLongDistanceMatching: From a7e33e3e10aef5d7e22d7d5bb455746e3480ffa9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 14:42:13 -0800 Subject: [PATCH 044/402] updated fuzz tests to use FileNamesTable* abstraction --- programs/util.c | 9 ++++++++ programs/util.h | 8 +++++++ tests/fuzz/regression_driver.c | 22 +++++++++---------- tests/regression/data.c | 40 +++++++++++++++------------------- tests/regression/data.h | 19 ---------------- 5 files changed, 46 insertions(+), 52 deletions(-) diff --git a/programs/util.c b/programs/util.c index dae26badb6a..769ec8b73b8 100644 --- a/programs/util.c +++ b/programs/util.c @@ -642,6 +642,15 @@ void UTIL_expandFNT(FileNamesTable** fnt, int followLinks) *fnt = newFNT; } +FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames) +{ + size_t const sizeof_FNTable = nbFilenames * sizeof(*filenames); + const char** const newFNTable = (const char**)malloc(sizeof_FNTable); + if (newFNTable==NULL) return NULL; + memcpy(newFNTable, filenames, sizeof_FNTable); + return UTIL_createFileNamesTable(newFNTable, nbFilenames, NULL); +} + /*-**************************************** * count the number of physical cores diff --git a/programs/util.h b/programs/util.h index 6808c4e3dd2..91a449a679a 100644 --- a/programs/util.h +++ b/programs/util.h @@ -204,6 +204,14 @@ UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2); */ void UTIL_expandFNT(FileNamesTable** fnt, int followLinks); +/*! UTIL_createFNT_fromROTable() : + * copy the @filenames pointer table inside the returned object. + * The names themselves are still stored in their original buffer, which must outlive the object. + * @return : a FileNamesTable* object, + * or NULL in case of error + */ +FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames); + /*! UTIL_createExpandedFNT() : * read names from @filenames, and expand those corresponding to directories * @return : an expanded FileNamesTable*, where each name is a file diff --git a/tests/fuzz/regression_driver.c b/tests/fuzz/regression_driver.c index e3ebcd5ced7..e91ef0def7e 100644 --- a/tests/fuzz/regression_driver.c +++ b/tests/fuzz/regression_driver.c @@ -18,24 +18,26 @@ int main(int argc, char const **argv) { size_t const kMaxFileSize = (size_t)1 << 27; int const kFollowLinks = 1; - char *fileNamesBuf = NULL; - char const **files = argv + 1; - unsigned numFiles = argc - 1; + FileNamesTable* files; + const char** const fnTable = argv + 1; + unsigned numFiles = (unsigned)(argc - 1); uint8_t *buffer = NULL; size_t bufferSize = 0; unsigned i; int ret; #ifdef UTIL_HAS_CREATEFILELIST - files = UTIL_createFileList(files, numFiles, &fileNamesBuf, &numFiles, - kFollowLinks); - if (!files) - numFiles = 0; + files = UTIL_createExpandedFNT(fnTable, numFiles, kFollowLinks); + if (!files) numFiles = 0; +#else + files = UTIL_createFNT_fromROTable(fnTable, numFiles); + if (!files) numFiles = 0; #endif + if (files) assert(numFiles == files->tableSize); if (numFiles == 0) fprintf(stderr, "WARNING: No files passed to %s\n", argv[0]); for (i = 0; i < numFiles; ++i) { - char const *fileName = files[i]; + char const *fileName = files->fileNames[i]; DEBUGLOG(3, "Running %s", fileName); size_t const fileSize = UTIL_getFileSize(fileName); size_t readSize; @@ -70,8 +72,6 @@ int main(int argc, char const **argv) { ret = 0; free(buffer); -#ifdef UTIL_HAS_CREATEFILELIST - UTIL_freeFileList(files, fileNamesBuf); -#endif + UTIL_freeFileNamesTable(files); return ret; } diff --git a/tests/regression/data.c b/tests/regression/data.c index 86e7687de5e..631a6f27f57 100644 --- a/tests/regression/data.c +++ b/tests/regression/data.c @@ -173,21 +173,10 @@ void data_buffer_free(data_buffer_t buffer) { * data filenames helpers. */ -data_filenames_t data_filenames_get(data_t const* data) { - data_filenames_t filenames = {.buffer = NULL, .size = 0}; - char const* path = data->data.path; - - filenames.filenames = UTIL_createFileList( - &path, - 1, - &filenames.buffer, - &filenames.size, - /* followLinks */ 0); - return filenames; -} - -void data_filenames_free(data_filenames_t filenames) { - UTIL_freeFileList(filenames.filenames, filenames.buffer); +FileNamesTable* data_filenames_get(data_t const* data) +{ + char const* const path = data->data.path; + return UTIL_createExpandedFNT(&path, 1, 0 /* followLinks */ ); } /** @@ -196,26 +185,33 @@ void data_filenames_free(data_filenames_t filenames) { data_buffers_t data_buffers_get(data_t const* data) { data_buffers_t buffers = {.size = 0}; - data_filenames_t filenames = data_filenames_get(data); - if (filenames.size == 0) + FileNamesTable* const filenames = data_filenames_get(data); + if (filenames == NULL) return buffers; + if (filenames->tableSize == 0) { + UTIL_freeFileNamesTable(filenames); return buffers; + } data_buffer_t* buffersPtr = - (data_buffer_t*)malloc(filenames.size * sizeof(data_buffer_t)); - if (buffersPtr == NULL) + (data_buffer_t*)malloc(filenames->tableSize * sizeof(*buffersPtr)); + if (buffersPtr == NULL) { + UTIL_freeFileNamesTable(filenames); return buffers; + } buffers.buffers = (data_buffer_t const*)buffersPtr; - buffers.size = filenames.size; + buffers.size = filenames->tableSize; - for (size_t i = 0; i < filenames.size; ++i) { - buffersPtr[i] = data_buffer_read(filenames.filenames[i]); + for (size_t i = 0; i < filenames->tableSize; ++i) { + buffersPtr[i] = data_buffer_read(filenames->fileNames[i]); if (buffersPtr[i].data == NULL) { data_buffers_t const kEmptyBuffer = {}; data_buffers_free(buffers); + UTIL_freeFileNamesTable(filenames); return kEmptyBuffer; } } + UTIL_freeFileNamesTable(filenames); return buffers; } diff --git a/tests/regression/data.h b/tests/regression/data.h index 717fe1294c1..2de8134f52a 100644 --- a/tests/regression/data.h +++ b/tests/regression/data.h @@ -102,25 +102,6 @@ int data_buffer_compare(data_buffer_t buffer1, data_buffer_t buffer2); */ void data_buffer_free(data_buffer_t buffer); -typedef struct { - char* buffer; - char const** filenames; - unsigned size; -} data_filenames_t; - -/** - * Get a recursive list of filenames in the data object. If it is a file, it - * will only contain one entry. If it is a directory, it will recursively walk - * the directory. - * - * @returns The list of filenames, which has size 0 and NULL pointers on error. - */ -data_filenames_t data_filenames_get(data_t const* data); - -/** - * Frees the filenames table. - */ -void data_filenames_free(data_filenames_t filenames); typedef struct { data_buffer_t const* buffers; From 485fec566568a50528dd2b0bd181f306c5515b3a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 14:43:14 -0800 Subject: [PATCH 045/402] removed experimental_dict_builders no longer required, can still be accessed by going to back to an earlier commit or release (<= v1.4.4) --- .../benchmarkDictBuilder/Makefile | 44 - .../benchmarkDictBuilder/README.md | 849 ------------------ .../benchmarkDictBuilder/benchmark.c | 442 --------- .../benchmarkDictBuilder/dictBuilder.h | 6 - .../benchmarkDictBuilder/test.sh | 2 - .../fastCover/Makefile | 54 -- .../fastCover/README.md | 24 - .../fastCover/fastCover.c | 809 ----------------- .../fastCover/fastCover.h | 57 -- .../fastCover/main.c | 183 ---- .../fastCover/test.sh | 15 - .../randomDictBuilder/Makefile | 52 -- .../randomDictBuilder/README.md | 20 - .../randomDictBuilder/io.c | 284 ------ .../randomDictBuilder/io.h | 60 -- .../randomDictBuilder/main.c | 161 ---- .../randomDictBuilder/random.c | 163 ---- .../randomDictBuilder/random.h | 29 - .../randomDictBuilder/test.sh | 14 - 19 files changed, 3268 deletions(-) delete mode 100644 contrib/experimental_dict_builders/benchmarkDictBuilder/Makefile delete mode 100644 contrib/experimental_dict_builders/benchmarkDictBuilder/README.md delete mode 100644 contrib/experimental_dict_builders/benchmarkDictBuilder/benchmark.c delete mode 100644 contrib/experimental_dict_builders/benchmarkDictBuilder/dictBuilder.h delete mode 100644 contrib/experimental_dict_builders/benchmarkDictBuilder/test.sh delete mode 100644 contrib/experimental_dict_builders/fastCover/Makefile delete mode 100644 contrib/experimental_dict_builders/fastCover/README.md delete mode 100644 contrib/experimental_dict_builders/fastCover/fastCover.c delete mode 100644 contrib/experimental_dict_builders/fastCover/fastCover.h delete mode 100644 contrib/experimental_dict_builders/fastCover/main.c delete mode 100644 contrib/experimental_dict_builders/fastCover/test.sh delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/Makefile delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/README.md delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/io.c delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/io.h delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/main.c delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/random.c delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/random.h delete mode 100644 contrib/experimental_dict_builders/randomDictBuilder/test.sh diff --git a/contrib/experimental_dict_builders/benchmarkDictBuilder/Makefile b/contrib/experimental_dict_builders/benchmarkDictBuilder/Makefile deleted file mode 100644 index 72ce04f2a56..00000000000 --- a/contrib/experimental_dict_builders/benchmarkDictBuilder/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -ARG := - -CC ?= gcc -CFLAGS ?= -O3 -INCLUDES := -I ../randomDictBuilder -I ../../../programs -I ../../../lib/common -I ../../../lib -I ../../../lib/dictBuilder - -RANDOM_FILE := ../randomDictBuilder/random.c -IO_FILE := ../randomDictBuilder/io.c - -all: run clean - -.PHONY: run -run: benchmark - echo "Benchmarking with $(ARG)" - ./benchmark $(ARG) - -.PHONY: test -test: benchmarkTest clean - -.PHONY: benchmarkTest -benchmarkTest: benchmark test.sh - sh test.sh - -benchmark: benchmark.o io.o random.o libzstd.a - $(CC) $(CFLAGS) benchmark.o io.o random.o libzstd.a -o benchmark - -benchmark.o: benchmark.c - $(CC) $(CFLAGS) $(INCLUDES) -c benchmark.c - -random.o: $(RANDOM_FILE) - $(CC) $(CFLAGS) $(INCLUDES) -c $(RANDOM_FILE) - -io.o: $(IO_FILE) - $(CC) $(CFLAGS) $(INCLUDES) -c $(IO_FILE) - -libzstd.a: - $(MAKE) -C ../../../lib libzstd.a - mv ../../../lib/libzstd.a . - -.PHONY: clean -clean: - rm -f *.o benchmark libzstd.a - $(MAKE) -C ../../../lib clean - echo "Cleaning is completed" diff --git a/contrib/experimental_dict_builders/benchmarkDictBuilder/README.md b/contrib/experimental_dict_builders/benchmarkDictBuilder/README.md deleted file mode 100644 index 6a6c7f1d216..00000000000 --- a/contrib/experimental_dict_builders/benchmarkDictBuilder/README.md +++ /dev/null @@ -1,849 +0,0 @@ -Benchmarking Dictionary Builder - -### Permitted Argument: -Input File/Directory (in=fileName): required; file/directory used to build dictionary; if directory, will operate recursively for files inside directory; can include multiple files/directories, each following "in=" - -###Running Test: -make test - -###Usage: -Benchmark given input files: make ARG= followed by permitted arguments - -### Examples: -make ARG="in=../../../lib/dictBuilder in=../../../lib/compress" - -###Benchmarking Result: -- First Cover is optimize cover, second Cover uses optimized d and k from first one. -- For every f value of fastCover, the first one is optimize fastCover and the second one uses optimized d and k from first one. This is run for accel values from 1 to 10. -- Fourth column is chosen d and fifth column is chosen k - -github: -NODICT 0.000004 2.999642 -RANDOM 0.024560 8.791189 -LEGACY 0.727109 8.173529 -COVER 40.565676 10.652243 8 1298 -COVER 3.608284 10.652243 8 1298 -FAST f=15 a=1 4.181024 10.570882 8 1154 -FAST f=15 a=1 0.040788 10.570882 8 1154 -FAST f=15 a=2 3.548352 10.574287 6 1970 -FAST f=15 a=2 0.035535 10.574287 6 1970 -FAST f=15 a=3 3.287364 10.613950 6 1010 -FAST f=15 a=3 0.032182 10.613950 6 1010 -FAST f=15 a=4 3.184976 10.573883 6 1058 -FAST f=15 a=4 0.029878 10.573883 6 1058 -FAST f=15 a=5 3.045513 10.580640 8 1154 -FAST f=15 a=5 0.022162 10.580640 8 1154 -FAST f=15 a=6 3.003296 10.583677 6 1010 -FAST f=15 a=6 0.028091 10.583677 6 1010 -FAST f=15 a=7 2.952655 10.622551 6 1106 -FAST f=15 a=7 0.02724 10.622551 6 1106 -FAST f=15 a=8 2.945674 10.614657 6 1010 -FAST f=15 a=8 0.027264 10.614657 6 1010 -FAST f=15 a=9 3.153439 10.564018 8 1154 -FAST f=15 a=9 0.020635 10.564018 8 1154 -FAST f=15 a=10 2.950416 10.511454 6 1010 -FAST f=15 a=10 0.026606 10.511454 6 1010 -FAST f=16 a=1 3.970029 10.681035 8 1154 -FAST f=16 a=1 0.038188 10.681035 8 1154 -FAST f=16 a=2 3.422892 10.484978 6 1874 -FAST f=16 a=2 0.034702 10.484978 6 1874 -FAST f=16 a=3 3.215836 10.632631 8 1154 -FAST f=16 a=3 0.026084 10.632631 8 1154 -FAST f=16 a=4 3.081353 10.626533 6 1106 -FAST f=16 a=4 0.030032 10.626533 6 1106 -FAST f=16 a=5 3.041241 10.545027 8 1922 -FAST f=16 a=5 0.022882 10.545027 8 1922 -FAST f=16 a=6 2.989390 10.638284 6 1874 -FAST f=16 a=6 0.028308 10.638284 6 1874 -FAST f=16 a=7 3.001581 10.797136 6 1106 -FAST f=16 a=7 0.027479 10.797136 6 1106 -FAST f=16 a=8 2.984107 10.658356 8 1058 -FAST f=16 a=8 0.021099 10.658356 8 1058 -FAST f=16 a=9 2.925788 10.523869 6 1010 -FAST f=16 a=9 0.026905 10.523869 6 1010 -FAST f=16 a=10 2.889605 10.745841 6 1874 -FAST f=16 a=10 0.026846 10.745841 6 1874 -FAST f=17 a=1 4.031953 10.672080 8 1202 -FAST f=17 a=1 0.040658 10.672080 8 1202 -FAST f=17 a=2 3.458107 10.589352 8 1106 -FAST f=17 a=2 0.02926 10.589352 8 1106 -FAST f=17 a=3 3.291189 10.662714 8 1154 -FAST f=17 a=3 0.026531 10.662714 8 1154 -FAST f=17 a=4 3.154950 10.549456 8 1346 -FAST f=17 a=4 0.024991 10.549456 8 1346 -FAST f=17 a=5 3.092271 10.541670 6 1202 -FAST f=17 a=5 0.038285 10.541670 6 1202 -FAST f=17 a=6 3.166146 10.729112 6 1874 -FAST f=17 a=6 0.038217 10.729112 6 1874 -FAST f=17 a=7 3.035467 10.810485 6 1106 -FAST f=17 a=7 0.036655 10.810485 6 1106 -FAST f=17 a=8 3.035668 10.530532 6 1058 -FAST f=17 a=8 0.037715 10.530532 6 1058 -FAST f=17 a=9 2.987917 10.589802 8 1922 -FAST f=17 a=9 0.02217 10.589802 8 1922 -FAST f=17 a=10 2.981647 10.722579 8 1106 -FAST f=17 a=10 0.021948 10.722579 8 1106 -FAST f=18 a=1 4.067144 10.634943 8 1154 -FAST f=18 a=1 0.041386 10.634943 8 1154 -FAST f=18 a=2 3.507377 10.546230 6 1970 -FAST f=18 a=2 0.037572 10.546230 6 1970 -FAST f=18 a=3 3.323015 10.648061 8 1154 -FAST f=18 a=3 0.028306 10.648061 8 1154 -FAST f=18 a=4 3.216735 10.705402 6 1010 -FAST f=18 a=4 0.030755 10.705402 6 1010 -FAST f=18 a=5 3.175794 10.588154 8 1874 -FAST f=18 a=5 0.025315 10.588154 8 1874 -FAST f=18 a=6 3.127459 10.751104 8 1106 -FAST f=18 a=6 0.023897 10.751104 8 1106 -FAST f=18 a=7 3.083017 10.780402 6 1106 -FAST f=18 a=7 0.029158 10.780402 6 1106 -FAST f=18 a=8 3.069700 10.547226 8 1346 -FAST f=18 a=8 0.024046 10.547226 8 1346 -FAST f=18 a=9 3.056591 10.674759 6 1010 -FAST f=18 a=9 0.028496 10.674759 6 1010 -FAST f=18 a=10 3.063588 10.737578 8 1106 -FAST f=18 a=10 0.023033 10.737578 8 1106 -FAST f=19 a=1 4.164041 10.650333 8 1154 -FAST f=19 a=1 0.042906 10.650333 8 1154 -FAST f=19 a=2 3.585409 10.577066 6 1058 -FAST f=19 a=2 0.038994 10.577066 6 1058 -FAST f=19 a=3 3.439643 10.639403 8 1154 -FAST f=19 a=3 0.028427 10.639403 8 1154 -FAST f=19 a=4 3.268869 10.554410 8 1298 -FAST f=19 a=4 0.026866 10.554410 8 1298 -FAST f=19 a=5 3.238225 10.615109 6 1010 -FAST f=19 a=5 0.03078 10.615109 6 1010 -FAST f=19 a=6 3.199558 10.609782 6 1874 -FAST f=19 a=6 0.030099 10.609782 6 1874 -FAST f=19 a=7 3.132395 10.794753 6 1106 -FAST f=19 a=7 0.028964 10.794753 6 1106 -FAST f=19 a=8 3.148446 10.554842 8 1298 -FAST f=19 a=8 0.024277 10.554842 8 1298 -FAST f=19 a=9 3.108324 10.668763 6 1010 -FAST f=19 a=9 0.02896 10.668763 6 1010 -FAST f=19 a=10 3.159863 10.757347 8 1106 -FAST f=19 a=10 0.023351 10.757347 8 1106 -FAST f=20 a=1 4.462698 10.661788 8 1154 -FAST f=20 a=1 0.047174 10.661788 8 1154 -FAST f=20 a=2 3.820269 10.678612 6 1106 -FAST f=20 a=2 0.040807 10.678612 6 1106 -FAST f=20 a=3 3.644955 10.648424 8 1154 -FAST f=20 a=3 0.031398 10.648424 8 1154 -FAST f=20 a=4 3.546257 10.559756 8 1298 -FAST f=20 a=4 0.029856 10.559756 8 1298 -FAST f=20 a=5 3.485248 10.646637 6 1010 -FAST f=20 a=5 0.033756 10.646637 6 1010 -FAST f=20 a=6 3.490438 10.775824 8 1106 -FAST f=20 a=6 0.028338 10.775824 8 1106 -FAST f=20 a=7 3.631289 10.801795 6 1106 -FAST f=20 a=7 0.035228 10.801795 6 1106 -FAST f=20 a=8 3.758936 10.545116 8 1346 -FAST f=20 a=8 0.027495 10.545116 8 1346 -FAST f=20 a=9 3.707024 10.677454 6 1010 -FAST f=20 a=9 0.031326 10.677454 6 1010 -FAST f=20 a=10 3.586593 10.756017 8 1106 -FAST f=20 a=10 0.027122 10.756017 8 1106 -FAST f=21 a=1 5.701396 10.655398 8 1154 -FAST f=21 a=1 0.067744 10.655398 8 1154 -FAST f=21 a=2 5.270542 10.650743 6 1106 -FAST f=21 a=2 0.052999 10.650743 6 1106 -FAST f=21 a=3 4.945294 10.652380 8 1154 -FAST f=21 a=3 0.052678 10.652380 8 1154 -FAST f=21 a=4 4.894079 10.543185 8 1298 -FAST f=21 a=4 0.04997 10.543185 8 1298 -FAST f=21 a=5 4.785417 10.630321 6 1010 -FAST f=21 a=5 0.045294 10.630321 6 1010 -FAST f=21 a=6 4.789381 10.664477 6 1874 -FAST f=21 a=6 0.046578 10.664477 6 1874 -FAST f=21 a=7 4.302955 10.805179 6 1106 -FAST f=21 a=7 0.041205 10.805179 6 1106 -FAST f=21 a=8 4.034630 10.551211 8 1298 -FAST f=21 a=8 0.040121 10.551211 8 1298 -FAST f=21 a=9 4.523868 10.799114 6 1010 -FAST f=21 a=9 0.043592 10.799114 6 1010 -FAST f=21 a=10 4.760736 10.750255 8 1106 -FAST f=21 a=10 0.043483 10.750255 8 1106 -FAST f=22 a=1 6.743064 10.640537 8 1154 -FAST f=22 a=1 0.086967 10.640537 8 1154 -FAST f=22 a=2 6.121739 10.626638 6 1970 -FAST f=22 a=2 0.066337 10.626638 6 1970 -FAST f=22 a=3 5.248851 10.640688 8 1154 -FAST f=22 a=3 0.054935 10.640688 8 1154 -FAST f=22 a=4 5.436579 10.588333 8 1298 -FAST f=22 a=4 0.064113 10.588333 8 1298 -FAST f=22 a=5 5.812815 10.652653 6 1010 -FAST f=22 a=5 0.058189 10.652653 6 1010 -FAST f=22 a=6 5.745472 10.666437 6 1874 -FAST f=22 a=6 0.057188 10.666437 6 1874 -FAST f=22 a=7 5.716393 10.806911 6 1106 -FAST f=22 a=7 0.056 10.806911 6 1106 -FAST f=22 a=8 5.698799 10.530784 8 1298 -FAST f=22 a=8 0.0583 10.530784 8 1298 -FAST f=22 a=9 5.710533 10.777391 6 1010 -FAST f=22 a=9 0.054945 10.777391 6 1010 -FAST f=22 a=10 5.685395 10.745023 8 1106 -FAST f=22 a=10 0.056526 10.745023 8 1106 -FAST f=23 a=1 7.836923 10.638828 8 1154 -FAST f=23 a=1 0.099522 10.638828 8 1154 -FAST f=23 a=2 6.627834 10.631061 6 1970 -FAST f=23 a=2 0.066769 10.631061 6 1970 -FAST f=23 a=3 5.602533 10.647288 8 1154 -FAST f=23 a=3 0.064513 10.647288 8 1154 -FAST f=23 a=4 6.005580 10.568747 8 1298 -FAST f=23 a=4 0.062022 10.568747 8 1298 -FAST f=23 a=5 5.481816 10.676921 6 1010 -FAST f=23 a=5 0.058959 10.676921 6 1010 -FAST f=23 a=6 5.460444 10.666194 6 1874 -FAST f=23 a=6 0.057687 10.666194 6 1874 -FAST f=23 a=7 5.659822 10.800377 6 1106 -FAST f=23 a=7 0.06783 10.800377 6 1106 -FAST f=23 a=8 6.826940 10.522167 8 1298 -FAST f=23 a=8 0.070533 10.522167 8 1298 -FAST f=23 a=9 6.804757 10.577799 8 1682 -FAST f=23 a=9 0.069949 10.577799 8 1682 -FAST f=23 a=10 6.774933 10.742093 8 1106 -FAST f=23 a=10 0.068395 10.742093 8 1106 -FAST f=24 a=1 8.444110 10.632783 8 1154 -FAST f=24 a=1 0.094357 10.632783 8 1154 -FAST f=24 a=2 7.289578 10.631061 6 1970 -FAST f=24 a=2 0.098515 10.631061 6 1970 -FAST f=24 a=3 8.619780 10.646289 8 1154 -FAST f=24 a=3 0.098041 10.646289 8 1154 -FAST f=24 a=4 8.508455 10.555199 8 1298 -FAST f=24 a=4 0.093885 10.555199 8 1298 -FAST f=24 a=5 8.471145 10.674363 6 1010 -FAST f=24 a=5 0.088676 10.674363 6 1010 -FAST f=24 a=6 8.426727 10.667228 6 1874 -FAST f=24 a=6 0.087247 10.667228 6 1874 -FAST f=24 a=7 8.356826 10.803027 6 1106 -FAST f=24 a=7 0.085835 10.803027 6 1106 -FAST f=24 a=8 6.756811 10.522049 8 1298 -FAST f=24 a=8 0.07107 10.522049 8 1298 -FAST f=24 a=9 6.548169 10.571882 8 1682 -FAST f=24 a=9 0.0713 10.571882 8 1682 -FAST f=24 a=10 8.238079 10.736453 8 1106 -FAST f=24 a=10 0.07004 10.736453 8 1106 - - -hg-commands: -NODICT 0.000005 2.425276 -RANDOM 0.046332 3.490331 -LEGACY 0.720351 3.911682 -COVER 45.507731 4.132653 8 386 -COVER 1.868810 4.132653 8 386 -FAST f=15 a=1 4.561427 3.866894 8 1202 -FAST f=15 a=1 0.048946 3.866894 8 1202 -FAST f=15 a=2 3.574462 3.892119 8 1538 -FAST f=15 a=2 0.033677 3.892119 8 1538 -FAST f=15 a=3 3.230227 3.888791 6 1346 -FAST f=15 a=3 0.034312 3.888791 6 1346 -FAST f=15 a=4 3.042388 3.899739 8 1010 -FAST f=15 a=4 0.024307 3.899739 8 1010 -FAST f=15 a=5 2.800148 3.896220 8 818 -FAST f=15 a=5 0.022331 3.896220 8 818 -FAST f=15 a=6 2.706518 3.882039 8 578 -FAST f=15 a=6 0.020955 3.882039 8 578 -FAST f=15 a=7 2.701820 3.885430 6 866 -FAST f=15 a=7 0.026074 3.885430 6 866 -FAST f=15 a=8 2.604445 3.906932 8 1826 -FAST f=15 a=8 0.021789 3.906932 8 1826 -FAST f=15 a=9 2.598568 3.870324 6 1682 -FAST f=15 a=9 0.026004 3.870324 6 1682 -FAST f=15 a=10 2.575920 3.920783 8 1442 -FAST f=15 a=10 0.020228 3.920783 8 1442 -FAST f=16 a=1 4.630623 4.001430 8 770 -FAST f=16 a=1 0.047497 4.001430 8 770 -FAST f=16 a=2 3.674721 3.974431 8 1874 -FAST f=16 a=2 0.035761 3.974431 8 1874 -FAST f=16 a=3 3.338384 3.978703 8 1010 -FAST f=16 a=3 0.029436 3.978703 8 1010 -FAST f=16 a=4 3.004412 3.983035 8 1010 -FAST f=16 a=4 0.025744 3.983035 8 1010 -FAST f=16 a=5 2.881892 3.987710 8 770 -FAST f=16 a=5 0.023211 3.987710 8 770 -FAST f=16 a=6 2.807410 3.952717 8 1298 -FAST f=16 a=6 0.023199 3.952717 8 1298 -FAST f=16 a=7 2.819623 3.994627 8 770 -FAST f=16 a=7 0.021806 3.994627 8 770 -FAST f=16 a=8 2.740092 3.954032 8 1826 -FAST f=16 a=8 0.0226 3.954032 8 1826 -FAST f=16 a=9 2.682564 3.969879 6 1442 -FAST f=16 a=9 0.026324 3.969879 6 1442 -FAST f=16 a=10 2.657959 3.969755 8 674 -FAST f=16 a=10 0.020413 3.969755 8 674 -FAST f=17 a=1 4.729228 4.046000 8 530 -FAST f=17 a=1 0.049703 4.046000 8 530 -FAST f=17 a=2 3.764510 3.991519 8 1970 -FAST f=17 a=2 0.038195 3.991519 8 1970 -FAST f=17 a=3 3.416992 4.006296 6 914 -FAST f=17 a=3 0.036244 4.006296 6 914 -FAST f=17 a=4 3.145626 3.979182 8 1970 -FAST f=17 a=4 0.028676 3.979182 8 1970 -FAST f=17 a=5 2.995070 4.050070 8 770 -FAST f=17 a=5 0.025707 4.050070 8 770 -FAST f=17 a=6 2.911833 4.040024 8 770 -FAST f=17 a=6 0.02453 4.040024 8 770 -FAST f=17 a=7 2.894796 4.015884 8 818 -FAST f=17 a=7 0.023956 4.015884 8 818 -FAST f=17 a=8 2.789962 4.039303 8 530 -FAST f=17 a=8 0.023219 4.039303 8 530 -FAST f=17 a=9 2.787625 3.996762 8 1634 -FAST f=17 a=9 0.023651 3.996762 8 1634 -FAST f=17 a=10 2.754796 4.005059 8 1058 -FAST f=17 a=10 0.022537 4.005059 8 1058 -FAST f=18 a=1 4.779117 4.038214 8 242 -FAST f=18 a=1 0.048814 4.038214 8 242 -FAST f=18 a=2 3.829753 4.045768 8 722 -FAST f=18 a=2 0.036541 4.045768 8 722 -FAST f=18 a=3 3.495053 4.021497 8 770 -FAST f=18 a=3 0.032648 4.021497 8 770 -FAST f=18 a=4 3.221395 4.039623 8 770 -FAST f=18 a=4 0.027818 4.039623 8 770 -FAST f=18 a=5 3.059369 4.050414 8 530 -FAST f=18 a=5 0.026296 4.050414 8 530 -FAST f=18 a=6 3.019292 4.010714 6 962 -FAST f=18 a=6 0.031104 4.010714 6 962 -FAST f=18 a=7 2.949322 4.031439 6 770 -FAST f=18 a=7 0.030745 4.031439 6 770 -FAST f=18 a=8 2.876425 4.032088 6 386 -FAST f=18 a=8 0.027407 4.032088 6 386 -FAST f=18 a=9 2.850958 4.053372 8 674 -FAST f=18 a=9 0.023799 4.053372 8 674 -FAST f=18 a=10 2.884352 4.020148 8 1730 -FAST f=18 a=10 0.024401 4.020148 8 1730 -FAST f=19 a=1 4.815669 4.061203 8 674 -FAST f=19 a=1 0.051425 4.061203 8 674 -FAST f=19 a=2 3.951356 4.013822 8 1442 -FAST f=19 a=2 0.039968 4.013822 8 1442 -FAST f=19 a=3 3.554682 4.050425 8 722 -FAST f=19 a=3 0.032725 4.050425 8 722 -FAST f=19 a=4 3.242585 4.054677 8 722 -FAST f=19 a=4 0.028194 4.054677 8 722 -FAST f=19 a=5 3.105909 4.064524 8 818 -FAST f=19 a=5 0.02675 4.064524 8 818 -FAST f=19 a=6 3.059901 4.036857 8 1250 -FAST f=19 a=6 0.026396 4.036857 8 1250 -FAST f=19 a=7 3.016151 4.068234 6 770 -FAST f=19 a=7 0.031501 4.068234 6 770 -FAST f=19 a=8 2.962902 4.077509 8 530 -FAST f=19 a=8 0.023333 4.077509 8 530 -FAST f=19 a=9 2.899607 4.067328 8 530 -FAST f=19 a=9 0.024553 4.067328 8 530 -FAST f=19 a=10 2.950978 4.059901 8 434 -FAST f=19 a=10 0.023852 4.059901 8 434 -FAST f=20 a=1 5.259834 4.027579 8 1634 -FAST f=20 a=1 0.061123 4.027579 8 1634 -FAST f=20 a=2 4.382150 4.025093 8 1634 -FAST f=20 a=2 0.048009 4.025093 8 1634 -FAST f=20 a=3 4.104323 4.060842 8 530 -FAST f=20 a=3 0.040965 4.060842 8 530 -FAST f=20 a=4 3.853340 4.023504 6 914 -FAST f=20 a=4 0.041072 4.023504 6 914 -FAST f=20 a=5 3.728841 4.018089 6 1634 -FAST f=20 a=5 0.037469 4.018089 6 1634 -FAST f=20 a=6 3.683045 4.069138 8 578 -FAST f=20 a=6 0.028011 4.069138 8 578 -FAST f=20 a=7 3.726973 4.063160 8 722 -FAST f=20 a=7 0.028437 4.063160 8 722 -FAST f=20 a=8 3.555073 4.057690 8 386 -FAST f=20 a=8 0.027588 4.057690 8 386 -FAST f=20 a=9 3.551095 4.067253 8 482 -FAST f=20 a=9 0.025976 4.067253 8 482 -FAST f=20 a=10 3.490127 4.068518 8 530 -FAST f=20 a=10 0.025971 4.068518 8 530 -FAST f=21 a=1 7.343816 4.064945 8 770 -FAST f=21 a=1 0.085035 4.064945 8 770 -FAST f=21 a=2 5.930894 4.048206 8 386 -FAST f=21 a=2 0.067349 4.048206 8 386 -FAST f=21 a=3 6.770775 4.063417 8 578 -FAST f=21 a=3 0.077104 4.063417 8 578 -FAST f=21 a=4 6.889409 4.066761 8 626 -FAST f=21 a=4 0.0717 4.066761 8 626 -FAST f=21 a=5 6.714896 4.051813 8 914 -FAST f=21 a=5 0.071026 4.051813 8 914 -FAST f=21 a=6 6.539890 4.047263 8 1922 -FAST f=21 a=6 0.07127 4.047263 8 1922 -FAST f=21 a=7 6.511052 4.068373 8 482 -FAST f=21 a=7 0.065467 4.068373 8 482 -FAST f=21 a=8 6.458788 4.071597 8 482 -FAST f=21 a=8 0.063817 4.071597 8 482 -FAST f=21 a=9 6.377591 4.052905 8 434 -FAST f=21 a=9 0.063112 4.052905 8 434 -FAST f=21 a=10 6.360752 4.047773 8 530 -FAST f=21 a=10 0.063606 4.047773 8 530 -FAST f=22 a=1 10.523471 4.040812 8 962 -FAST f=22 a=1 0.14214 4.040812 8 962 -FAST f=22 a=2 9.454758 4.059396 8 914 -FAST f=22 a=2 0.118343 4.059396 8 914 -FAST f=22 a=3 9.043197 4.043019 8 1922 -FAST f=22 a=3 0.109798 4.043019 8 1922 -FAST f=22 a=4 8.716261 4.044819 8 770 -FAST f=22 a=4 0.099687 4.044819 8 770 -FAST f=22 a=5 8.529472 4.070576 8 530 -FAST f=22 a=5 0.093127 4.070576 8 530 -FAST f=22 a=6 8.424241 4.070565 8 722 -FAST f=22 a=6 0.093703 4.070565 8 722 -FAST f=22 a=7 8.403391 4.070591 8 578 -FAST f=22 a=7 0.089763 4.070591 8 578 -FAST f=22 a=8 8.285221 4.089171 8 530 -FAST f=22 a=8 0.087716 4.089171 8 530 -FAST f=22 a=9 8.282506 4.047470 8 722 -FAST f=22 a=9 0.089773 4.047470 8 722 -FAST f=22 a=10 8.241809 4.064151 8 818 -FAST f=22 a=10 0.090413 4.064151 8 818 -FAST f=23 a=1 12.389208 4.051635 6 530 -FAST f=23 a=1 0.147796 4.051635 6 530 -FAST f=23 a=2 11.300910 4.042835 6 914 -FAST f=23 a=2 0.133178 4.042835 6 914 -FAST f=23 a=3 10.879455 4.047415 8 626 -FAST f=23 a=3 0.129571 4.047415 8 626 -FAST f=23 a=4 10.522718 4.038269 6 914 -FAST f=23 a=4 0.118121 4.038269 6 914 -FAST f=23 a=5 10.348043 4.066884 8 434 -FAST f=23 a=5 0.112098 4.066884 8 434 -FAST f=23 a=6 10.238630 4.048635 8 1010 -FAST f=23 a=6 0.120281 4.048635 8 1010 -FAST f=23 a=7 10.213255 4.061809 8 530 -FAST f=23 a=7 0.1121 4.061809 8 530 -FAST f=23 a=8 10.107879 4.074104 8 818 -FAST f=23 a=8 0.116544 4.074104 8 818 -FAST f=23 a=9 10.063424 4.064811 8 674 -FAST f=23 a=9 0.109045 4.064811 8 674 -FAST f=23 a=10 10.035801 4.054918 8 530 -FAST f=23 a=10 0.108735 4.054918 8 530 -FAST f=24 a=1 14.963878 4.073490 8 722 -FAST f=24 a=1 0.206344 4.073490 8 722 -FAST f=24 a=2 13.833472 4.036100 8 962 -FAST f=24 a=2 0.17486 4.036100 8 962 -FAST f=24 a=3 13.404631 4.026281 6 1106 -FAST f=24 a=3 0.153961 4.026281 6 1106 -FAST f=24 a=4 13.041164 4.065448 8 674 -FAST f=24 a=4 0.155509 4.065448 8 674 -FAST f=24 a=5 12.879412 4.054636 8 674 -FAST f=24 a=5 0.148282 4.054636 8 674 -FAST f=24 a=6 12.773736 4.081376 8 530 -FAST f=24 a=6 0.142563 4.081376 8 530 -FAST f=24 a=7 12.711310 4.059834 8 770 -FAST f=24 a=7 0.149321 4.059834 8 770 -FAST f=24 a=8 12.635459 4.052050 8 1298 -FAST f=24 a=8 0.15095 4.052050 8 1298 -FAST f=24 a=9 12.558104 4.076516 8 722 -FAST f=24 a=9 0.144361 4.076516 8 722 -FAST f=24 a=10 10.661348 4.062137 8 818 -FAST f=24 a=10 0.108232 4.062137 8 818 - - -hg-changelog: -NODICT 0.000017 1.377590 -RANDOM 0.186171 2.097487 -LEGACY 1.670867 2.058907 -COVER 173.561948 2.189685 8 98 -COVER 4.811180 2.189685 8 98 -FAST f=15 a=1 18.685906 2.129682 8 434 -FAST f=15 a=1 0.173376 2.129682 8 434 -FAST f=15 a=2 12.928259 2.131890 8 482 -FAST f=15 a=2 0.102582 2.131890 8 482 -FAST f=15 a=3 11.132343 2.128027 8 386 -FAST f=15 a=3 0.077122 2.128027 8 386 -FAST f=15 a=4 10.120683 2.125797 8 434 -FAST f=15 a=4 0.065175 2.125797 8 434 -FAST f=15 a=5 9.479092 2.127697 8 386 -FAST f=15 a=5 0.057905 2.127697 8 386 -FAST f=15 a=6 9.159523 2.127132 8 1682 -FAST f=15 a=6 0.058604 2.127132 8 1682 -FAST f=15 a=7 8.724003 2.129914 8 434 -FAST f=15 a=7 0.0493 2.129914 8 434 -FAST f=15 a=8 8.595001 2.127137 8 338 -FAST f=15 a=8 0.0474 2.127137 8 338 -FAST f=15 a=9 8.356405 2.125512 8 482 -FAST f=15 a=9 0.046126 2.125512 8 482 -FAST f=15 a=10 8.207111 2.126066 8 338 -FAST f=15 a=10 0.043292 2.126066 8 338 -FAST f=16 a=1 18.464436 2.144040 8 242 -FAST f=16 a=1 0.172156 2.144040 8 242 -FAST f=16 a=2 12.844825 2.148171 8 194 -FAST f=16 a=2 0.099619 2.148171 8 194 -FAST f=16 a=3 11.082568 2.140837 8 290 -FAST f=16 a=3 0.079165 2.140837 8 290 -FAST f=16 a=4 10.066749 2.144405 8 386 -FAST f=16 a=4 0.068411 2.144405 8 386 -FAST f=16 a=5 9.501121 2.140720 8 386 -FAST f=16 a=5 0.061316 2.140720 8 386 -FAST f=16 a=6 9.179332 2.139478 8 386 -FAST f=16 a=6 0.056322 2.139478 8 386 -FAST f=16 a=7 8.849438 2.142412 8 194 -FAST f=16 a=7 0.050493 2.142412 8 194 -FAST f=16 a=8 8.810919 2.143454 8 434 -FAST f=16 a=8 0.051304 2.143454 8 434 -FAST f=16 a=9 8.553900 2.140339 8 194 -FAST f=16 a=9 0.047285 2.140339 8 194 -FAST f=16 a=10 8.398027 2.143130 8 386 -FAST f=16 a=10 0.046386 2.143130 8 386 -FAST f=17 a=1 18.644657 2.157192 8 98 -FAST f=17 a=1 0.173884 2.157192 8 98 -FAST f=17 a=2 13.071242 2.159830 8 146 -FAST f=17 a=2 0.10388 2.159830 8 146 -FAST f=17 a=3 11.332366 2.153654 6 194 -FAST f=17 a=3 0.08983 2.153654 6 194 -FAST f=17 a=4 10.362413 2.156813 8 242 -FAST f=17 a=4 0.070389 2.156813 8 242 -FAST f=17 a=5 9.808159 2.155098 6 338 -FAST f=17 a=5 0.072661 2.155098 6 338 -FAST f=17 a=6 9.451165 2.153845 6 146 -FAST f=17 a=6 0.064959 2.153845 6 146 -FAST f=17 a=7 9.163097 2.155424 6 242 -FAST f=17 a=7 0.064323 2.155424 6 242 -FAST f=17 a=8 9.047276 2.156640 8 242 -FAST f=17 a=8 0.053382 2.156640 8 242 -FAST f=17 a=9 8.807671 2.152396 8 146 -FAST f=17 a=9 0.049617 2.152396 8 146 -FAST f=17 a=10 8.649827 2.152370 8 146 -FAST f=17 a=10 0.047849 2.152370 8 146 -FAST f=18 a=1 18.809502 2.168116 8 98 -FAST f=18 a=1 0.175226 2.168116 8 98 -FAST f=18 a=2 13.756502 2.170870 6 242 -FAST f=18 a=2 0.119507 2.170870 6 242 -FAST f=18 a=3 12.059748 2.163094 6 98 -FAST f=18 a=3 0.093912 2.163094 6 98 -FAST f=18 a=4 11.410294 2.172372 8 98 -FAST f=18 a=4 0.073048 2.172372 8 98 -FAST f=18 a=5 10.560297 2.166388 8 98 -FAST f=18 a=5 0.065136 2.166388 8 98 -FAST f=18 a=6 10.071390 2.162672 8 98 -FAST f=18 a=6 0.059402 2.162672 8 98 -FAST f=18 a=7 10.084214 2.166624 6 194 -FAST f=18 a=7 0.073276 2.166624 6 194 -FAST f=18 a=8 9.953226 2.167454 8 98 -FAST f=18 a=8 0.053659 2.167454 8 98 -FAST f=18 a=9 8.982461 2.161593 6 146 -FAST f=18 a=9 0.05955 2.161593 6 146 -FAST f=18 a=10 8.986092 2.164373 6 242 -FAST f=18 a=10 0.059135 2.164373 6 242 -FAST f=19 a=1 18.908277 2.176021 8 98 -FAST f=19 a=1 0.177316 2.176021 8 98 -FAST f=19 a=2 13.471313 2.176103 8 98 -FAST f=19 a=2 0.106344 2.176103 8 98 -FAST f=19 a=3 11.571406 2.172812 8 98 -FAST f=19 a=3 0.083293 2.172812 8 98 -FAST f=19 a=4 10.632775 2.177770 6 146 -FAST f=19 a=4 0.079864 2.177770 6 146 -FAST f=19 a=5 10.030190 2.175574 6 146 -FAST f=19 a=5 0.07223 2.175574 6 146 -FAST f=19 a=6 9.717818 2.169997 8 98 -FAST f=19 a=6 0.060049 2.169997 8 98 -FAST f=19 a=7 9.397531 2.172770 8 146 -FAST f=19 a=7 0.057188 2.172770 8 146 -FAST f=19 a=8 9.281061 2.175822 8 98 -FAST f=19 a=8 0.053711 2.175822 8 98 -FAST f=19 a=9 9.165242 2.169849 6 146 -FAST f=19 a=9 0.059898 2.169849 6 146 -FAST f=19 a=10 9.048763 2.173394 8 98 -FAST f=19 a=10 0.049757 2.173394 8 98 -FAST f=20 a=1 21.166917 2.183923 6 98 -FAST f=20 a=1 0.205425 2.183923 6 98 -FAST f=20 a=2 15.642753 2.182349 6 98 -FAST f=20 a=2 0.135957 2.182349 6 98 -FAST f=20 a=3 14.053730 2.173544 6 98 -FAST f=20 a=3 0.11266 2.173544 6 98 -FAST f=20 a=4 15.270019 2.183656 8 98 -FAST f=20 a=4 0.107892 2.183656 8 98 -FAST f=20 a=5 15.497927 2.174661 6 98 -FAST f=20 a=5 0.100305 2.174661 6 98 -FAST f=20 a=6 13.973505 2.172391 8 98 -FAST f=20 a=6 0.087565 2.172391 8 98 -FAST f=20 a=7 14.083296 2.172443 8 98 -FAST f=20 a=7 0.078062 2.172443 8 98 -FAST f=20 a=8 12.560048 2.175581 8 98 -FAST f=20 a=8 0.070282 2.175581 8 98 -FAST f=20 a=9 13.078645 2.173975 6 146 -FAST f=20 a=9 0.081041 2.173975 6 146 -FAST f=20 a=10 12.823328 2.177778 8 98 -FAST f=20 a=10 0.074522 2.177778 8 98 -FAST f=21 a=1 29.825370 2.183057 6 98 -FAST f=21 a=1 0.334453 2.183057 6 98 -FAST f=21 a=2 29.476474 2.182752 8 98 -FAST f=21 a=2 0.286602 2.182752 8 98 -FAST f=21 a=3 25.937186 2.175867 8 98 -FAST f=21 a=3 0.17626 2.175867 8 98 -FAST f=21 a=4 20.413865 2.179780 8 98 -FAST f=21 a=4 0.206085 2.179780 8 98 -FAST f=21 a=5 20.541889 2.178328 6 146 -FAST f=21 a=5 0.199157 2.178328 6 146 -FAST f=21 a=6 21.090670 2.174443 6 146 -FAST f=21 a=6 0.190645 2.174443 6 146 -FAST f=21 a=7 20.221569 2.177384 6 146 -FAST f=21 a=7 0.184278 2.177384 6 146 -FAST f=21 a=8 20.322357 2.179456 6 98 -FAST f=21 a=8 0.178458 2.179456 6 98 -FAST f=21 a=9 20.683912 2.174396 6 146 -FAST f=21 a=9 0.190829 2.174396 6 146 -FAST f=21 a=10 20.840865 2.174905 8 98 -FAST f=21 a=10 0.172515 2.174905 8 98 -FAST f=22 a=1 36.822827 2.181612 6 98 -FAST f=22 a=1 0.437389 2.181612 6 98 -FAST f=22 a=2 30.616902 2.183142 8 98 -FAST f=22 a=2 0.324284 2.183142 8 98 -FAST f=22 a=3 28.472482 2.178130 8 98 -FAST f=22 a=3 0.236538 2.178130 8 98 -FAST f=22 a=4 25.847028 2.181878 8 98 -FAST f=22 a=4 0.263744 2.181878 8 98 -FAST f=22 a=5 27.095881 2.180775 8 98 -FAST f=22 a=5 0.24988 2.180775 8 98 -FAST f=22 a=6 25.939172 2.170916 8 98 -FAST f=22 a=6 0.240033 2.170916 8 98 -FAST f=22 a=7 27.064194 2.177849 8 98 -FAST f=22 a=7 0.242383 2.177849 8 98 -FAST f=22 a=8 25.140221 2.178216 8 98 -FAST f=22 a=8 0.237601 2.178216 8 98 -FAST f=22 a=9 25.505283 2.177455 6 146 -FAST f=22 a=9 0.223217 2.177455 6 146 -FAST f=22 a=10 24.529362 2.176705 6 98 -FAST f=22 a=10 0.222876 2.176705 6 98 -FAST f=23 a=1 39.127310 2.183006 6 98 -FAST f=23 a=1 0.417338 2.183006 6 98 -FAST f=23 a=2 32.468161 2.183524 6 98 -FAST f=23 a=2 0.351645 2.183524 6 98 -FAST f=23 a=3 31.577620 2.172604 6 98 -FAST f=23 a=3 0.319659 2.172604 6 98 -FAST f=23 a=4 30.129247 2.183932 6 98 -FAST f=23 a=4 0.307239 2.183932 6 98 -FAST f=23 a=5 29.103376 2.183529 6 146 -FAST f=23 a=5 0.285533 2.183529 6 146 -FAST f=23 a=6 29.776045 2.174367 8 98 -FAST f=23 a=6 0.276846 2.174367 8 98 -FAST f=23 a=7 28.940407 2.178022 6 146 -FAST f=23 a=7 0.274082 2.178022 6 146 -FAST f=23 a=8 29.256009 2.179462 6 98 -FAST f=23 a=8 0.26949 2.179462 6 98 -FAST f=23 a=9 29.347312 2.170407 8 98 -FAST f=23 a=9 0.265034 2.170407 8 98 -FAST f=23 a=10 29.140081 2.171762 8 98 -FAST f=23 a=10 0.259183 2.171762 8 98 -FAST f=24 a=1 44.871179 2.182115 6 98 -FAST f=24 a=1 0.509433 2.182115 6 98 -FAST f=24 a=2 38.694867 2.180549 8 98 -FAST f=24 a=2 0.406695 2.180549 8 98 -FAST f=24 a=3 38.363769 2.172821 8 98 -FAST f=24 a=3 0.359581 2.172821 8 98 -FAST f=24 a=4 36.580797 2.184142 8 98 -FAST f=24 a=4 0.340614 2.184142 8 98 -FAST f=24 a=5 33.125701 2.183301 8 98 -FAST f=24 a=5 0.324874 2.183301 8 98 -FAST f=24 a=6 34.776068 2.173019 6 146 -FAST f=24 a=6 0.340397 2.173019 6 146 -FAST f=24 a=7 34.417625 2.176561 6 146 -FAST f=24 a=7 0.308223 2.176561 6 146 -FAST f=24 a=8 35.470291 2.182161 6 98 -FAST f=24 a=8 0.307724 2.182161 6 98 -FAST f=24 a=9 34.927252 2.172682 6 146 -FAST f=24 a=9 0.300598 2.172682 6 146 -FAST f=24 a=10 33.238355 2.173395 6 98 -FAST f=24 a=10 0.249916 2.173395 6 98 - - -hg-manifest: -NODICT 0.000004 1.866377 -RANDOM 0.696346 2.309436 -LEGACY 7.064527 2.506977 -COVER 876.312865 2.582528 8 434 -COVER 35.684533 2.582528 8 434 -FAST f=15 a=1 76.618201 2.404013 8 1202 -FAST f=15 a=1 0.700722 2.404013 8 1202 -FAST f=15 a=2 49.213058 2.409248 6 1826 -FAST f=15 a=2 0.473393 2.409248 6 1826 -FAST f=15 a=3 41.753197 2.409677 8 1490 -FAST f=15 a=3 0.336848 2.409677 8 1490 -FAST f=15 a=4 38.648295 2.407996 8 1538 -FAST f=15 a=4 0.283952 2.407996 8 1538 -FAST f=15 a=5 36.144936 2.402895 8 1874 -FAST f=15 a=5 0.270128 2.402895 8 1874 -FAST f=15 a=6 35.484675 2.394873 8 1586 -FAST f=15 a=6 0.251637 2.394873 8 1586 -FAST f=15 a=7 34.280599 2.397311 8 1778 -FAST f=15 a=7 0.23984 2.397311 8 1778 -FAST f=15 a=8 32.122572 2.396089 6 1490 -FAST f=15 a=8 0.251508 2.396089 6 1490 -FAST f=15 a=9 29.909842 2.390092 6 1970 -FAST f=15 a=9 0.251233 2.390092 6 1970 -FAST f=15 a=10 30.102938 2.400086 6 1682 -FAST f=15 a=10 0.23688 2.400086 6 1682 -FAST f=16 a=1 67.750401 2.475460 6 1346 -FAST f=16 a=1 0.796035 2.475460 6 1346 -FAST f=16 a=2 52.812027 2.480860 6 1730 -FAST f=16 a=2 0.480384 2.480860 6 1730 -FAST f=16 a=3 44.179259 2.469304 8 1970 -FAST f=16 a=3 0.332657 2.469304 8 1970 -FAST f=16 a=4 37.612728 2.478208 6 1970 -FAST f=16 a=4 0.32498 2.478208 6 1970 -FAST f=16 a=5 35.056222 2.475568 6 1298 -FAST f=16 a=5 0.302824 2.475568 6 1298 -FAST f=16 a=6 34.713012 2.486079 8 1730 -FAST f=16 a=6 0.24755 2.486079 8 1730 -FAST f=16 a=7 33.713687 2.477180 6 1682 -FAST f=16 a=7 0.280358 2.477180 6 1682 -FAST f=16 a=8 31.571412 2.475418 8 1538 -FAST f=16 a=8 0.241241 2.475418 8 1538 -FAST f=16 a=9 31.608069 2.478263 8 1922 -FAST f=16 a=9 0.241764 2.478263 8 1922 -FAST f=16 a=10 31.358002 2.472263 8 1442 -FAST f=16 a=10 0.221661 2.472263 8 1442 -FAST f=17 a=1 66.185775 2.536085 6 1346 -FAST f=17 a=1 0.713549 2.536085 6 1346 -FAST f=17 a=2 50.365000 2.546105 8 1298 -FAST f=17 a=2 0.467846 2.546105 8 1298 -FAST f=17 a=3 42.712843 2.536250 8 1298 -FAST f=17 a=3 0.34047 2.536250 8 1298 -FAST f=17 a=4 39.514227 2.535555 8 1442 -FAST f=17 a=4 0.302989 2.535555 8 1442 -FAST f=17 a=5 35.189292 2.524925 8 1202 -FAST f=17 a=5 0.273451 2.524925 8 1202 -FAST f=17 a=6 35.791683 2.523466 8 1202 -FAST f=17 a=6 0.268261 2.523466 8 1202 -FAST f=17 a=7 37.416136 2.526625 6 1010 -FAST f=17 a=7 0.277558 2.526625 6 1010 -FAST f=17 a=8 37.084707 2.533274 6 1250 -FAST f=17 a=8 0.285104 2.533274 6 1250 -FAST f=17 a=9 34.183814 2.532765 8 1298 -FAST f=17 a=9 0.235133 2.532765 8 1298 -FAST f=17 a=10 31.149235 2.528722 8 1346 -FAST f=17 a=10 0.232679 2.528722 8 1346 -FAST f=18 a=1 72.942176 2.559857 6 386 -FAST f=18 a=1 0.718618 2.559857 6 386 -FAST f=18 a=2 51.690440 2.559572 8 290 -FAST f=18 a=2 0.403978 2.559572 8 290 -FAST f=18 a=3 45.344908 2.561040 8 962 -FAST f=18 a=3 0.357205 2.561040 8 962 -FAST f=18 a=4 39.804522 2.558446 8 1010 -FAST f=18 a=4 0.310526 2.558446 8 1010 -FAST f=18 a=5 38.134888 2.561811 8 626 -FAST f=18 a=5 0.273743 2.561811 8 626 -FAST f=18 a=6 35.091890 2.555518 8 722 -FAST f=18 a=6 0.260135 2.555518 8 722 -FAST f=18 a=7 34.639523 2.562938 8 290 -FAST f=18 a=7 0.234294 2.562938 8 290 -FAST f=18 a=8 36.076431 2.563567 8 1586 -FAST f=18 a=8 0.274075 2.563567 8 1586 -FAST f=18 a=9 36.376433 2.560950 8 722 -FAST f=18 a=9 0.240106 2.560950 8 722 -FAST f=18 a=10 32.624790 2.559340 8 578 -FAST f=18 a=10 0.234704 2.559340 8 578 -FAST f=19 a=1 70.513761 2.572441 8 194 -FAST f=19 a=1 0.726112 2.572441 8 194 -FAST f=19 a=2 59.263032 2.574560 8 482 -FAST f=19 a=2 0.451554 2.574560 8 482 -FAST f=19 a=3 51.509594 2.571546 6 194 -FAST f=19 a=3 0.393014 2.571546 6 194 -FAST f=19 a=4 55.393906 2.573386 8 482 -FAST f=19 a=4 0.38819 2.573386 8 482 -FAST f=19 a=5 43.201736 2.567589 8 674 -FAST f=19 a=5 0.292155 2.567589 8 674 -FAST f=19 a=6 42.911687 2.572666 6 434 -FAST f=19 a=6 0.303988 2.572666 6 434 -FAST f=19 a=7 44.687591 2.573613 6 290 -FAST f=19 a=7 0.308721 2.573613 6 290 -FAST f=19 a=8 37.372868 2.571039 6 194 -FAST f=19 a=8 0.287137 2.571039 6 194 -FAST f=19 a=9 36.074230 2.566473 6 482 -FAST f=19 a=9 0.280721 2.566473 6 482 -FAST f=19 a=10 33.731720 2.570306 8 194 -FAST f=19 a=10 0.224073 2.570306 8 194 -FAST f=20 a=1 79.670634 2.581146 6 290 -FAST f=20 a=1 0.899986 2.581146 6 290 -FAST f=20 a=2 58.827141 2.579782 8 386 -FAST f=20 a=2 0.602288 2.579782 8 386 -FAST f=20 a=3 51.289004 2.579627 8 722 -FAST f=20 a=3 0.446091 2.579627 8 722 -FAST f=20 a=4 47.711068 2.581508 8 722 -FAST f=20 a=4 0.473007 2.581508 8 722 -FAST f=20 a=5 47.402929 2.578062 6 434 -FAST f=20 a=5 0.497131 2.578062 6 434 -FAST f=20 a=6 54.797102 2.577365 8 482 -FAST f=20 a=6 0.515061 2.577365 8 482 -FAST f=20 a=7 51.370877 2.583050 8 386 -FAST f=20 a=7 0.402878 2.583050 8 386 -FAST f=20 a=8 51.437931 2.574875 6 242 -FAST f=20 a=8 0.453094 2.574875 6 242 -FAST f=20 a=9 44.105456 2.576700 6 242 -FAST f=20 a=9 0.456633 2.576700 6 242 -FAST f=20 a=10 44.447580 2.578305 8 338 -FAST f=20 a=10 0.409121 2.578305 8 338 -FAST f=21 a=1 113.031686 2.582449 6 242 -FAST f=21 a=1 1.456971 2.582449 6 242 -FAST f=21 a=2 97.700932 2.582124 8 194 -FAST f=21 a=2 1.072078 2.582124 8 194 -FAST f=21 a=3 96.563648 2.585479 8 434 -FAST f=21 a=3 0.949528 2.585479 8 434 -FAST f=21 a=4 90.597813 2.582366 6 386 -FAST f=21 a=4 0.76944 2.582366 6 386 -FAST f=21 a=5 86.815980 2.579043 8 434 -FAST f=21 a=5 0.858167 2.579043 8 434 -FAST f=21 a=6 91.235820 2.578378 8 530 -FAST f=21 a=6 0.684274 2.578378 8 530 -FAST f=21 a=7 84.392788 2.581243 8 386 -FAST f=21 a=7 0.814386 2.581243 8 386 -FAST f=21 a=8 82.052310 2.582547 8 338 -FAST f=21 a=8 0.822633 2.582547 8 338 -FAST f=21 a=9 74.696074 2.579319 8 194 -FAST f=21 a=9 0.811028 2.579319 8 194 -FAST f=21 a=10 76.211170 2.578766 8 290 -FAST f=21 a=10 0.809715 2.578766 8 290 -FAST f=22 a=1 138.976871 2.580478 8 194 -FAST f=22 a=1 1.748932 2.580478 8 194 -FAST f=22 a=2 120.164097 2.583633 8 386 -FAST f=22 a=2 1.333239 2.583633 8 386 -FAST f=22 a=3 111.986474 2.582566 6 194 -FAST f=22 a=3 1.305734 2.582566 6 194 -FAST f=22 a=4 108.548148 2.583068 6 194 -FAST f=22 a=4 1.314026 2.583068 6 194 -FAST f=22 a=5 103.173017 2.583495 6 290 -FAST f=22 a=5 1.228664 2.583495 6 290 -FAST f=22 a=6 108.421262 2.582349 8 530 -FAST f=22 a=6 1.076773 2.582349 8 530 -FAST f=22 a=7 103.284127 2.581022 8 386 -FAST f=22 a=7 1.112117 2.581022 8 386 -FAST f=22 a=8 96.330279 2.581073 8 290 -FAST f=22 a=8 1.109303 2.581073 8 290 -FAST f=22 a=9 97.651348 2.580075 6 194 -FAST f=22 a=9 0.933032 2.580075 6 194 -FAST f=22 a=10 101.660621 2.584886 8 194 -FAST f=22 a=10 0.796823 2.584886 8 194 -FAST f=23 a=1 159.322978 2.581474 6 242 -FAST f=23 a=1 2.015878 2.581474 6 242 -FAST f=23 a=2 134.331775 2.581619 8 194 -FAST f=23 a=2 1.545845 2.581619 8 194 -FAST f=23 a=3 127.724552 2.579888 6 338 -FAST f=23 a=3 1.444496 2.579888 6 338 -FAST f=23 a=4 126.077675 2.578137 6 242 -FAST f=23 a=4 1.364394 2.578137 6 242 -FAST f=23 a=5 124.914027 2.580843 8 338 -FAST f=23 a=5 1.116059 2.580843 8 338 -FAST f=23 a=6 122.874153 2.577637 6 338 -FAST f=23 a=6 1.164584 2.577637 6 338 -FAST f=23 a=7 123.099257 2.582715 6 386 -FAST f=23 a=7 1.354042 2.582715 6 386 -FAST f=23 a=8 122.026753 2.577681 8 194 -FAST f=23 a=8 1.210966 2.577681 8 194 -FAST f=23 a=9 121.164312 2.584599 6 290 -FAST f=23 a=9 1.174859 2.584599 6 290 -FAST f=23 a=10 117.462222 2.580358 8 194 -FAST f=23 a=10 1.075258 2.580358 8 194 -FAST f=24 a=1 169.539659 2.581642 6 194 -FAST f=24 a=1 1.916804 2.581642 6 194 -FAST f=24 a=2 160.539270 2.580421 6 290 -FAST f=24 a=2 1.71087 2.580421 6 290 -FAST f=24 a=3 155.455874 2.580449 6 242 -FAST f=24 a=3 1.60307 2.580449 6 242 -FAST f=24 a=4 147.630320 2.582953 6 338 -FAST f=24 a=4 1.396364 2.582953 6 338 -FAST f=24 a=5 133.767428 2.580589 6 290 -FAST f=24 a=5 1.19933 2.580589 6 290 -FAST f=24 a=6 146.437535 2.579453 8 194 -FAST f=24 a=6 1.385405 2.579453 8 194 -FAST f=24 a=7 147.227507 2.584155 8 386 -FAST f=24 a=7 1.48942 2.584155 8 386 -FAST f=24 a=8 138.005773 2.584115 8 194 -FAST f=24 a=8 1.352 2.584115 8 194 -FAST f=24 a=9 141.442625 2.582902 8 290 -FAST f=24 a=9 1.39647 2.582902 8 290 -FAST f=24 a=10 142.157446 2.582701 8 434 -FAST f=24 a=10 1.498889 2.582701 8 434 diff --git a/contrib/experimental_dict_builders/benchmarkDictBuilder/benchmark.c b/contrib/experimental_dict_builders/benchmarkDictBuilder/benchmark.c deleted file mode 100644 index cd943797bde..00000000000 --- a/contrib/experimental_dict_builders/benchmarkDictBuilder/benchmark.c +++ /dev/null @@ -1,442 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* strcmp, strlen */ -#include /* errno */ -#include -#include -#include "random.h" -#include "dictBuilder.h" -#include "zstd_internal.h" /* includes zstd.h */ -#include "io.h" -#include "util.h" -#include "zdict.h" - - - -/*-************************************* -* Console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - -static const U64 g_refreshRate = SEC_TO_MICRO / 6; -static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; - -#define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \ - if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \ - { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ - if (displayLevel>=4) fflush(stderr); } } } - - -/*-************************************* -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAY("Error %i : ", error); \ - DISPLAY(__VA_ARGS__); \ - DISPLAY("\n"); \ - exit(error); \ -} - - -/*-************************************* -* Constants -***************************************/ -static const unsigned g_defaultMaxDictSize = 110 KB; -#define DEFAULT_CLEVEL 3 -#define DEFAULT_DISPLAYLEVEL 2 - - -/*-************************************* -* Struct -***************************************/ -typedef struct { - const void* dictBuffer; - size_t dictSize; -} dictInfo; - - -/*-************************************* -* Dictionary related operations -***************************************/ -/** createDictFromFiles() : - * Based on type of param given, train dictionary using the corresponding algorithm - * @return dictInfo containing dictionary buffer and dictionary size - */ -dictInfo* createDictFromFiles(sampleInfo *info, unsigned maxDictSize, - ZDICT_random_params_t *randomParams, ZDICT_cover_params_t *coverParams, - ZDICT_legacy_params_t *legacyParams, ZDICT_fastCover_params_t *fastParams) { - unsigned const displayLevel = randomParams ? randomParams->zParams.notificationLevel : - coverParams ? coverParams->zParams.notificationLevel : - legacyParams ? legacyParams->zParams.notificationLevel : - fastParams ? fastParams->zParams.notificationLevel : - DEFAULT_DISPLAYLEVEL; /* no dict */ - void* const dictBuffer = malloc(maxDictSize); - - dictInfo* dInfo = NULL; - - /* Checks */ - if (!dictBuffer) - EXM_THROW(12, "not enough memory for trainFromFiles"); /* should not happen */ - - { size_t dictSize; - if(randomParams) { - dictSize = ZDICT_trainFromBuffer_random(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *randomParams); - }else if(coverParams) { - /* Run the optimize version if either k or d is not provided */ - if (!coverParams->d || !coverParams->k){ - dictSize = ZDICT_optimizeTrainFromBuffer_cover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, coverParams); - } else { - dictSize = ZDICT_trainFromBuffer_cover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *coverParams); - } - } else if(legacyParams) { - dictSize = ZDICT_trainFromBuffer_legacy(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *legacyParams); - } else if(fastParams) { - /* Run the optimize version if either k or d is not provided */ - if (!fastParams->d || !fastParams->k) { - dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, fastParams); - } else { - dictSize = ZDICT_trainFromBuffer_fastCover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *fastParams); - } - } else { - dictSize = 0; - } - if (ZDICT_isError(dictSize)) { - DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */ - free(dictBuffer); - return dInfo; - } - dInfo = (dictInfo *)malloc(sizeof(dictInfo)); - dInfo->dictBuffer = dictBuffer; - dInfo->dictSize = dictSize; - } - return dInfo; -} - - -/** compressWithDict() : - * Compress samples from sample buffer given dictionary stored on dictionary buffer and compression level - * @return compression ratio - */ -double compressWithDict(sampleInfo *srcInfo, dictInfo* dInfo, int compressionLevel, int displayLevel) { - /* Local variables */ - size_t totalCompressedSize = 0; - size_t totalOriginalSize = 0; - const unsigned hasDict = dInfo->dictSize > 0 ? 1 : 0; - double cRatio; - size_t dstCapacity; - int i; - - /* Pointers */ - ZSTD_CDict *cdict = NULL; - ZSTD_CCtx* cctx = NULL; - size_t *offsets = NULL; - void* dst = NULL; - - /* Allocate dst with enough space to compress the maximum sized sample */ - { - size_t maxSampleSize = 0; - for (i = 0; i < srcInfo->nbSamples; i++) { - maxSampleSize = MAX(srcInfo->samplesSizes[i], maxSampleSize); - } - dstCapacity = ZSTD_compressBound(maxSampleSize); - dst = malloc(dstCapacity); - } - - /* Calculate offset for each sample */ - offsets = (size_t *)malloc((srcInfo->nbSamples + 1) * sizeof(size_t)); - offsets[0] = 0; - for (i = 1; i <= srcInfo->nbSamples; i++) { - offsets[i] = offsets[i - 1] + srcInfo->samplesSizes[i - 1]; - } - - /* Create the cctx */ - cctx = ZSTD_createCCtx(); - if(!cctx || !dst) { - cRatio = -1; - goto _cleanup; - } - - /* Create CDict if there's a dictionary stored on buffer */ - if (hasDict) { - cdict = ZSTD_createCDict(dInfo->dictBuffer, dInfo->dictSize, compressionLevel); - if(!cdict) { - cRatio = -1; - goto _cleanup; - } - } - - /* Compress each sample and sum their sizes*/ - const BYTE *const samples = (const BYTE *)srcInfo->srcBuffer; - for (i = 0; i < srcInfo->nbSamples; i++) { - size_t compressedSize; - if(hasDict) { - compressedSize = ZSTD_compress_usingCDict(cctx, dst, dstCapacity, samples + offsets[i], srcInfo->samplesSizes[i], cdict); - } else { - compressedSize = ZSTD_compressCCtx(cctx, dst, dstCapacity,samples + offsets[i], srcInfo->samplesSizes[i], compressionLevel); - } - if (ZSTD_isError(compressedSize)) { - cRatio = -1; - goto _cleanup; - } - totalCompressedSize += compressedSize; - } - - /* Sum original sizes */ - for (i = 0; inbSamples; i++) { - totalOriginalSize += srcInfo->samplesSizes[i]; - } - - /* Calculate compression ratio */ - DISPLAYLEVEL(2, "original size is %lu\n", totalOriginalSize); - DISPLAYLEVEL(2, "compressed size is %lu\n", totalCompressedSize); - cRatio = (double)totalOriginalSize/(double)totalCompressedSize; - -_cleanup: - free(dst); - free(offsets); - ZSTD_freeCCtx(cctx); - ZSTD_freeCDict(cdict); - return cRatio; -} - - -/** FreeDictInfo() : - * Free memory allocated for dictInfo - */ -void freeDictInfo(dictInfo* info) { - if (!info) return; - if (info->dictBuffer) free((void*)(info->dictBuffer)); - free(info); -} - - - -/*-******************************************************** - * Benchmarking functions -**********************************************************/ -/** benchmarkDictBuilder() : - * Measure how long a dictionary builder takes and compression ratio with the dictionary built - * @return 0 if benchmark successfully, 1 otherwise - */ -int benchmarkDictBuilder(sampleInfo *srcInfo, unsigned maxDictSize, ZDICT_random_params_t *randomParam, - ZDICT_cover_params_t *coverParam, ZDICT_legacy_params_t *legacyParam, - ZDICT_fastCover_params_t *fastParam) { - /* Local variables */ - const unsigned displayLevel = randomParam ? randomParam->zParams.notificationLevel : - coverParam ? coverParam->zParams.notificationLevel : - legacyParam ? legacyParam->zParams.notificationLevel : - fastParam ? fastParam->zParams.notificationLevel: - DEFAULT_DISPLAYLEVEL; /* no dict */ - const char* name = randomParam ? "RANDOM" : - coverParam ? "COVER" : - legacyParam ? "LEGACY" : - fastParam ? "FAST": - "NODICT"; /* no dict */ - const unsigned cLevel = randomParam ? randomParam->zParams.compressionLevel : - coverParam ? coverParam->zParams.compressionLevel : - legacyParam ? legacyParam->zParams.compressionLevel : - fastParam ? fastParam->zParams.compressionLevel: - DEFAULT_CLEVEL; /* no dict */ - int result = 0; - - /* Calculate speed */ - const UTIL_time_t begin = UTIL_getTime(); - dictInfo* dInfo = createDictFromFiles(srcInfo, maxDictSize, randomParam, coverParam, legacyParam, fastParam); - const U64 timeMicro = UTIL_clockSpanMicro(begin); - const double timeSec = timeMicro / (double)SEC_TO_MICRO; - if (!dInfo) { - DISPLAYLEVEL(1, "%s does not train successfully\n", name); - result = 1; - goto _cleanup; - } - DISPLAYLEVEL(1, "%s took %f seconds to execute \n", name, timeSec); - - /* Calculate compression ratio */ - const double cRatio = compressWithDict(srcInfo, dInfo, cLevel, displayLevel); - if (cRatio < 0) { - DISPLAYLEVEL(1, "Compressing with %s dictionary does not work\n", name); - result = 1; - goto _cleanup; - - } - DISPLAYLEVEL(1, "Compression ratio with %s dictionary is %f\n", name, cRatio); - -_cleanup: - freeDictInfo(dInfo); - return result; -} - - - -int main(int argCount, const char* argv[]) -{ - const int displayLevel = DEFAULT_DISPLAYLEVEL; - const char* programName = argv[0]; - int result = 0; - - /* Initialize arguments to default values */ - unsigned k = 200; - unsigned d = 8; - unsigned f; - unsigned accel; - unsigned i; - const unsigned cLevel = DEFAULT_CLEVEL; - const unsigned dictID = 0; - const unsigned maxDictSize = g_defaultMaxDictSize; - - /* Initialize table to store input files */ - const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); - unsigned filenameIdx = 0; - - char* fileNamesBuf = NULL; - unsigned fileNamesNb = filenameIdx; - const int followLinks = 0; - const char** extendedFileList = NULL; - - /* Parse arguments */ - for (i = 1; i < argCount; i++) { - const char* argument = argv[i]; - if (longCommandWArg(&argument, "in=")) { - filenameTable[filenameIdx] = argument; - filenameIdx++; - continue; - } - DISPLAYLEVEL(1, "benchmark: Incorrect parameters\n"); - return 1; - } - - /* Get the list of all files recursively (because followLinks==0)*/ - extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, - &fileNamesNb, followLinks); - if (extendedFileList) { - unsigned u; - for (u=0; u /* fprintf */ -#include /* malloc, free, qsort */ -#include /* memset */ -#include /* clock */ -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" -#include "fastCover.h" -#include "zstd_internal.h" /* includes zstd.h */ -#include "zdict.h" - - -/*-************************************* -* Constants -***************************************/ -#define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((U32)-1) : ((U32)1 GB)) -#define FASTCOVER_MAX_F 32 -#define DEFAULT_SPLITPOINT 1.0 - -/*-************************************* -* Console display -***************************************/ -static int g_displayLevel = 2; -#define DISPLAY(...) \ - { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } -#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ - if (displayLevel >= l) { \ - DISPLAY(__VA_ARGS__); \ - } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ -#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) - -#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ - if (displayLevel >= l) { \ - if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \ - g_time = clock(); \ - DISPLAY(__VA_ARGS__); \ - } \ - } -#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; - - -/*-************************************* -* Hash Functions -***************************************/ -static const U64 prime6bytes = 227718039650203ULL; -static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; } -static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); } - -static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; -static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } -static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } - - -/** - * Hash the d-byte value pointed to by p and mod 2^f - */ -static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 h, unsigned d) { - if (d == 6) { - return ZSTD_hash6Ptr(p, h) & ((1 << h) - 1); - } - return ZSTD_hash8Ptr(p, h) & ((1 << h) - 1); -} - - -/*-************************************* -* Context -***************************************/ -typedef struct { - const BYTE *samples; - size_t *offsets; - const size_t *samplesSizes; - size_t nbSamples; - size_t nbTrainSamples; - size_t nbTestSamples; - size_t nbDmers; - U32 *freqs; - U16 *segmentFreqs; - unsigned d; -} FASTCOVER_ctx_t; - - -/*-************************************* -* Helper functions -***************************************/ -/** - * Returns the sum of the sample sizes. - */ -static size_t FASTCOVER_sum(const size_t *samplesSizes, unsigned nbSamples) { - size_t sum = 0; - unsigned i; - for (i = 0; i < nbSamples; ++i) { - sum += samplesSizes[i]; - } - return sum; -} - - -/*-************************************* -* fast functions -***************************************/ -/** - * A segment is a range in the source as well as the score of the segment. - */ -typedef struct { - U32 begin; - U32 end; - U32 score; -} FASTCOVER_segment_t; - - -/** - * Selects the best segment in an epoch. - * Segments of are scored according to the function: - * - * Let F(d) be the frequency of all dmers with hash value d. - * Let S_i be hash value of the dmer at position i of segment S which has length k. - * - * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) - * - * Once the dmer with hash value d is in the dictionary we set F(d) = F(d)/2. - */ -static FASTCOVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx, - U32 *freqs, U32 begin,U32 end, - ZDICT_fastCover_params_t parameters) { - /* Constants */ - const U32 k = parameters.k; - const U32 d = parameters.d; - const U32 dmersInK = k - d + 1; - /* Try each segment (activeSegment) and save the best (bestSegment) */ - FASTCOVER_segment_t bestSegment = {0, 0, 0}; - FASTCOVER_segment_t activeSegment; - /* Reset the activeDmers in the segment */ - /* The activeSegment starts at the beginning of the epoch. */ - activeSegment.begin = begin; - activeSegment.end = begin; - activeSegment.score = 0; - { - /* Slide the activeSegment through the whole epoch. - * Save the best segment in bestSegment. - */ - while (activeSegment.end < end) { - /* Get hash value of current dmer */ - const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, parameters.f, ctx->d); - /* Add frequency of this index to score if this is the first occurrence of index in active segment */ - if (ctx->segmentFreqs[index] == 0) { - activeSegment.score += freqs[index]; - } - ctx->segmentFreqs[index] += 1; - /* Increment end of segment */ - activeSegment.end += 1; - /* If the window is now too large, drop the first position */ - if (activeSegment.end - activeSegment.begin == dmersInK + 1) { - /* Get hash value of the dmer to be eliminated from active segment */ - const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, parameters.f, ctx->d); - ctx->segmentFreqs[delIndex] -= 1; - /* Subtract frequency of this index from score if this is the last occurrence of this index in active segment */ - if (ctx->segmentFreqs[delIndex] == 0) { - activeSegment.score -= freqs[delIndex]; - } - /* Increment start of segment */ - activeSegment.begin += 1; - } - /* If this segment is the best so far save it */ - if (activeSegment.score > bestSegment.score) { - bestSegment = activeSegment; - } - } - /* Zero out rest of segmentFreqs array */ - while (activeSegment.begin < end) { - const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, parameters.f, ctx->d); - ctx->segmentFreqs[delIndex] -= 1; - activeSegment.begin += 1; - } - } - { - /* Trim off the zero frequency head and tail from the segment. */ - U32 newBegin = bestSegment.end; - U32 newEnd = bestSegment.begin; - U32 pos; - for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) { - const size_t index = FASTCOVER_hashPtrToIndex(ctx->samples + pos, parameters.f, ctx->d); - U32 freq = freqs[index]; - if (freq != 0) { - newBegin = MIN(newBegin, pos); - newEnd = pos + 1; - } - } - bestSegment.begin = newBegin; - bestSegment.end = newEnd; - } - { - /* Zero the frequency of hash value of each dmer covered by the chosen segment. */ - U32 pos; - for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) { - const size_t i = FASTCOVER_hashPtrToIndex(ctx->samples + pos, parameters.f, ctx->d); - freqs[i] = 0; - } - } - return bestSegment; -} - -/** - * Check the validity of the parameters. - * Returns non-zero if the parameters are valid and 0 otherwise. - */ -static int FASTCOVER_checkParameters(ZDICT_fastCover_params_t parameters, - size_t maxDictSize) { - /* k, d, and f are required parameters */ - if (parameters.d == 0 || parameters.k == 0 || parameters.f == 0) { - return 0; - } - /* d has to be 6 or 8 */ - if (parameters.d != 6 && parameters.d != 8) { - return 0; - } - /* 0 < f <= FASTCOVER_MAX_F */ - if (parameters.f > FASTCOVER_MAX_F) { - return 0; - } - /* k <= maxDictSize */ - if (parameters.k > maxDictSize) { - return 0; - } - /* d <= k */ - if (parameters.d > parameters.k) { - return 0; - } - /* 0 < splitPoint <= 1 */ - if (parameters.splitPoint <= 0 || parameters.splitPoint > 1) { - return 0; - } - return 1; -} - - -/** - * Clean up a context initialized with `FASTCOVER_ctx_init()`. - */ -static void FASTCOVER_ctx_destroy(FASTCOVER_ctx_t *ctx) { - if (!ctx) { - return; - } - if (ctx->segmentFreqs) { - free(ctx->segmentFreqs); - ctx->segmentFreqs = NULL; - } - if (ctx->freqs) { - free(ctx->freqs); - ctx->freqs = NULL; - } - if (ctx->offsets) { - free(ctx->offsets); - ctx->offsets = NULL; - } -} - -/** - * Calculate for frequency of hash value of each dmer in ctx->samples - */ -static void FASTCOVER_computeFrequency(U32 *freqs, unsigned f, FASTCOVER_ctx_t *ctx){ - size_t start; /* start of current dmer */ - for (unsigned i = 0; i < ctx->nbTrainSamples; i++) { - size_t currSampleStart = ctx->offsets[i]; - size_t currSampleEnd = ctx->offsets[i+1]; - start = currSampleStart; - while (start + ctx->d <= currSampleEnd) { - const size_t dmerIndex = FASTCOVER_hashPtrToIndex(ctx->samples + start, f, ctx->d); - freqs[dmerIndex]++; - start++; - } - } -} - -/** - * Prepare a context for dictionary building. - * The context is only dependent on the parameter `d` and can used multiple - * times. - * Returns 1 on success or zero on error. - * The context must be destroyed with `FASTCOVER_ctx_destroy()`. - */ -static int FASTCOVER_ctx_init(FASTCOVER_ctx_t *ctx, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, - unsigned d, double splitPoint, unsigned f) { - const BYTE *const samples = (const BYTE *)samplesBuffer; - const size_t totalSamplesSize = FASTCOVER_sum(samplesSizes, nbSamples); - /* Split samples into testing and training sets */ - const unsigned nbTrainSamples = splitPoint < 1.0 ? (unsigned)((double)nbSamples * splitPoint) : nbSamples; - const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples; - const size_t trainingSamplesSize = splitPoint < 1.0 ? FASTCOVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize; - const size_t testSamplesSize = splitPoint < 1.0 ? FASTCOVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize; - /* Checks */ - if (totalSamplesSize < MAX(d, sizeof(U64)) || - totalSamplesSize >= (size_t)FASTCOVER_MAX_SAMPLES_SIZE) { - DISPLAYLEVEL(1, "Total samples size is too large (%u MB), maximum size is %u MB\n", - (U32)(totalSamplesSize >> 20), (FASTCOVER_MAX_SAMPLES_SIZE >> 20)); - return 0; - } - /* Check if there are at least 5 training samples */ - if (nbTrainSamples < 5) { - DISPLAYLEVEL(1, "Total number of training samples is %u and is invalid.", nbTrainSamples); - return 0; - } - /* Check if there's testing sample */ - if (nbTestSamples < 1) { - DISPLAYLEVEL(1, "Total number of testing samples is %u and is invalid.", nbTestSamples); - return 0; - } - /* Zero the context */ - memset(ctx, 0, sizeof(*ctx)); - DISPLAYLEVEL(2, "Training on %u samples of total size %u\n", nbTrainSamples, - (U32)trainingSamplesSize); - DISPLAYLEVEL(2, "Testing on %u samples of total size %u\n", nbTestSamples, - (U32)testSamplesSize); - - ctx->samples = samples; - ctx->samplesSizes = samplesSizes; - ctx->nbSamples = nbSamples; - ctx->nbTrainSamples = nbTrainSamples; - ctx->nbTestSamples = nbTestSamples; - ctx->nbDmers = trainingSamplesSize - d + 1; - ctx->d = d; - - /* The offsets of each file */ - ctx->offsets = (size_t *)malloc((nbSamples + 1) * sizeof(size_t)); - if (!ctx->offsets) { - DISPLAYLEVEL(1, "Failed to allocate scratch buffers\n"); - FASTCOVER_ctx_destroy(ctx); - return 0; - } - - /* Fill offsets from the samplesSizes */ - { - U32 i; - ctx->offsets[0] = 0; - for (i = 1; i <= nbSamples; ++i) { - ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1]; - } - } - - /* Initialize frequency array of size 2^f */ - ctx->freqs = (U32 *)calloc((1 << f), sizeof(U32)); - ctx->segmentFreqs = (U16 *)calloc((1 << f), sizeof(U16)); - DISPLAYLEVEL(2, "Computing frequencies\n"); - FASTCOVER_computeFrequency(ctx->freqs, f, ctx); - - return 1; -} - - -/** - * Given the prepared context build the dictionary. - */ -static size_t FASTCOVER_buildDictionary(const FASTCOVER_ctx_t *ctx, U32 *freqs, - void *dictBuffer, - size_t dictBufferCapacity, - ZDICT_fastCover_params_t parameters){ - BYTE *const dict = (BYTE *)dictBuffer; - size_t tail = dictBufferCapacity; - /* Divide the data up into epochs of equal size. - * We will select at least one segment from each epoch. - */ - const U32 epochs = MAX(1, (U32)(dictBufferCapacity / parameters.k)); - const U32 epochSize = (U32)(ctx->nbDmers / epochs); - size_t epoch; - DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", epochs, - epochSize); - /* Loop through the epochs until there are no more segments or the dictionary - * is full. - */ - for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) { - const U32 epochBegin = (U32)(epoch * epochSize); - const U32 epochEnd = epochBegin + epochSize; - size_t segmentSize; - /* Select a segment */ - FASTCOVER_segment_t segment = FASTCOVER_selectSegment( - ctx, freqs, epochBegin, epochEnd, parameters); - - /* If the segment covers no dmers, then we are out of content */ - if (segment.score == 0) { - break; - } - - /* Trim the segment if necessary and if it is too small then we are done */ - segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); - if (segmentSize < parameters.d) { - break; - } - - /* We fill the dictionary from the back to allow the best segments to be - * referenced with the smallest offsets. - */ - tail -= segmentSize; - memcpy(dict + tail, ctx->samples + segment.begin, segmentSize); - DISPLAYUPDATE( - 2, "\r%u%% ", - (U32)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity)); - } - DISPLAYLEVEL(2, "\r%79s\r", ""); - return tail; -} - - -/** - * FASTCOVER_best_t is used for two purposes: - * 1. Synchronizing threads. - * 2. Saving the best parameters and dictionary. - * - * All of the methods except FASTCOVER_best_init() are thread safe if zstd is - * compiled with multithreaded support. - */ -typedef struct fast_best_s { - ZSTD_pthread_mutex_t mutex; - ZSTD_pthread_cond_t cond; - size_t liveJobs; - void *dict; - size_t dictSize; - ZDICT_fastCover_params_t parameters; - size_t compressedSize; -} FASTCOVER_best_t; - -/** - * Initialize the `FASTCOVER_best_t`. - */ -static void FASTCOVER_best_init(FASTCOVER_best_t *best) { - if (best==NULL) return; /* compatible with init on NULL */ - (void)ZSTD_pthread_mutex_init(&best->mutex, NULL); - (void)ZSTD_pthread_cond_init(&best->cond, NULL); - best->liveJobs = 0; - best->dict = NULL; - best->dictSize = 0; - best->compressedSize = (size_t)-1; - memset(&best->parameters, 0, sizeof(best->parameters)); -} - -/** - * Wait until liveJobs == 0. - */ -static void FASTCOVER_best_wait(FASTCOVER_best_t *best) { - if (!best) { - return; - } - ZSTD_pthread_mutex_lock(&best->mutex); - while (best->liveJobs != 0) { - ZSTD_pthread_cond_wait(&best->cond, &best->mutex); - } - ZSTD_pthread_mutex_unlock(&best->mutex); -} - -/** - * Call FASTCOVER_best_wait() and then destroy the FASTCOVER_best_t. - */ -static void FASTCOVER_best_destroy(FASTCOVER_best_t *best) { - if (!best) { - return; - } - FASTCOVER_best_wait(best); - if (best->dict) { - free(best->dict); - } - ZSTD_pthread_mutex_destroy(&best->mutex); - ZSTD_pthread_cond_destroy(&best->cond); -} - -/** - * Called when a thread is about to be launched. - * Increments liveJobs. - */ -static void FASTCOVER_best_start(FASTCOVER_best_t *best) { - if (!best) { - return; - } - ZSTD_pthread_mutex_lock(&best->mutex); - ++best->liveJobs; - ZSTD_pthread_mutex_unlock(&best->mutex); -} - -/** - * Called when a thread finishes executing, both on error or success. - * Decrements liveJobs and signals any waiting threads if liveJobs == 0. - * If this dictionary is the best so far save it and its parameters. - */ -static void FASTCOVER_best_finish(FASTCOVER_best_t *best, size_t compressedSize, - ZDICT_fastCover_params_t parameters, void *dict, - size_t dictSize) { - if (!best) { - return; - } - { - size_t liveJobs; - ZSTD_pthread_mutex_lock(&best->mutex); - --best->liveJobs; - liveJobs = best->liveJobs; - /* If the new dictionary is better */ - if (compressedSize < best->compressedSize) { - /* Allocate space if necessary */ - if (!best->dict || best->dictSize < dictSize) { - if (best->dict) { - free(best->dict); - } - best->dict = malloc(dictSize); - if (!best->dict) { - best->compressedSize = ERROR(GENERIC); - best->dictSize = 0; - return; - } - } - /* Save the dictionary, parameters, and size */ - memcpy(best->dict, dict, dictSize); - best->dictSize = dictSize; - best->parameters = parameters; - best->compressedSize = compressedSize; - } - ZSTD_pthread_mutex_unlock(&best->mutex); - if (liveJobs == 0) { - ZSTD_pthread_cond_broadcast(&best->cond); - } - } -} - -/** - * Parameters for FASTCOVER_tryParameters(). - */ -typedef struct FASTCOVER_tryParameters_data_s { - const FASTCOVER_ctx_t *ctx; - FASTCOVER_best_t *best; - size_t dictBufferCapacity; - ZDICT_fastCover_params_t parameters; -} FASTCOVER_tryParameters_data_t; - -/** - * Tries a set of parameters and updates the FASTCOVER_best_t with the results. - * This function is thread safe if zstd is compiled with multithreaded support. - * It takes its parameters as an *OWNING* opaque pointer to support threading. - */ -static void FASTCOVER_tryParameters(void *opaque) { - /* Save parameters as local variables */ - FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t *)opaque; - const FASTCOVER_ctx_t *const ctx = data->ctx; - const ZDICT_fastCover_params_t parameters = data->parameters; - size_t dictBufferCapacity = data->dictBufferCapacity; - size_t totalCompressedSize = ERROR(GENERIC); - /* Allocate space for hash table, dict, and freqs */ - BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity); - U32 *freqs = (U32*) malloc((1 << parameters.f) * sizeof(U32)); - if (!dict || !freqs) { - DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); - goto _cleanup; - } - /* Copy the frequencies because we need to modify them */ - memcpy(freqs, ctx->freqs, (1 << parameters.f) * sizeof(U32)); - /* Build the dictionary */ - { - const size_t tail = FASTCOVER_buildDictionary(ctx, freqs, dict, - dictBufferCapacity, parameters); - - dictBufferCapacity = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, - parameters.zParams); - if (ZDICT_isError(dictBufferCapacity)) { - DISPLAYLEVEL(1, "Failed to finalize dictionary\n"); - goto _cleanup; - } - } - /* Check total compressed size */ - { - /* Pointers */ - ZSTD_CCtx *cctx; - ZSTD_CDict *cdict; - void *dst; - /* Local variables */ - size_t dstCapacity; - size_t i; - /* Allocate dst with enough space to compress the maximum sized sample */ - { - size_t maxSampleSize = 0; - i = parameters.splitPoint < 1.0 ? ctx->nbTrainSamples : 0; - for (; i < ctx->nbSamples; ++i) { - maxSampleSize = MAX(ctx->samplesSizes[i], maxSampleSize); - } - dstCapacity = ZSTD_compressBound(maxSampleSize); - dst = malloc(dstCapacity); - } - /* Create the cctx and cdict */ - cctx = ZSTD_createCCtx(); - cdict = ZSTD_createCDict(dict, dictBufferCapacity, - parameters.zParams.compressionLevel); - if (!dst || !cctx || !cdict) { - goto _compressCleanup; - } - /* Compress each sample and sum their sizes (or error) */ - totalCompressedSize = dictBufferCapacity; - i = parameters.splitPoint < 1.0 ? ctx->nbTrainSamples : 0; - for (; i < ctx->nbSamples; ++i) { - const size_t size = ZSTD_compress_usingCDict( - cctx, dst, dstCapacity, ctx->samples + ctx->offsets[i], - ctx->samplesSizes[i], cdict); - if (ZSTD_isError(size)) { - totalCompressedSize = ERROR(GENERIC); - goto _compressCleanup; - } - totalCompressedSize += size; - } - _compressCleanup: - ZSTD_freeCCtx(cctx); - ZSTD_freeCDict(cdict); - if (dst) { - free(dst); - } - } - -_cleanup: - FASTCOVER_best_finish(data->best, totalCompressedSize, parameters, dict, - dictBufferCapacity); - free(data); - if (dict) { - free(dict); - } - if (freqs) { - free(freqs); - } -} - -ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, ZDICT_fastCover_params_t parameters) { - BYTE* const dict = (BYTE*)dictBuffer; - FASTCOVER_ctx_t ctx; - parameters.splitPoint = 1.0; - /* Initialize global data */ - g_displayLevel = parameters.zParams.notificationLevel; - /* Checks */ - if (!FASTCOVER_checkParameters(parameters, dictBufferCapacity)) { - DISPLAYLEVEL(1, "FASTCOVER parameters incorrect\n"); - return ERROR(GENERIC); - } - if (nbSamples == 0) { - DISPLAYLEVEL(1, "FASTCOVER must have at least one input file\n"); - return ERROR(GENERIC); - } - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { - DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", - ZDICT_DICTSIZE_MIN); - return ERROR(dstSize_tooSmall); - } - /* Initialize context */ - if (!FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, - parameters.d, parameters.splitPoint, parameters.f)) { - DISPLAYLEVEL(1, "Failed to initialize context\n"); - return ERROR(GENERIC); - } - /* Build the dictionary */ - DISPLAYLEVEL(2, "Building dictionary\n"); - { - const size_t tail = FASTCOVER_buildDictionary(&ctx, ctx.freqs, dictBuffer, - dictBufferCapacity, parameters); - - const size_t dictionarySize = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - samplesBuffer, samplesSizes, (unsigned)ctx.nbTrainSamples, - parameters.zParams); - if (!ZSTD_isError(dictionarySize)) { - DISPLAYLEVEL(2, "Constructed dictionary of size %u\n", - (U32)dictionarySize); - } - FASTCOVER_ctx_destroy(&ctx); - return dictionarySize; - } -} - - - -ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, - ZDICT_fastCover_params_t *parameters) { - /* constants */ - const unsigned nbThreads = parameters->nbThreads; - const double splitPoint = - parameters->splitPoint <= 0.0 ? DEFAULT_SPLITPOINT : parameters->splitPoint; - const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; - const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d; - const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k; - const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k; - const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps; - const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); - const unsigned kIterations = - (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); - const unsigned f = parameters->f == 0 ? 23 : parameters->f; - - /* Local variables */ - const int displayLevel = parameters->zParams.notificationLevel; - unsigned iteration = 1; - unsigned d; - unsigned k; - FASTCOVER_best_t best; - POOL_ctx *pool = NULL; - - /* Checks */ - if (splitPoint <= 0 || splitPoint > 1) { - LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n"); - return ERROR(GENERIC); - } - if (kMinK < kMaxD || kMaxK < kMinK) { - LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect k\n"); - return ERROR(GENERIC); - } - if (nbSamples == 0) { - DISPLAYLEVEL(1, "FASTCOVER must have at least one input file\n"); - return ERROR(GENERIC); - } - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { - DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", - ZDICT_DICTSIZE_MIN); - return ERROR(dstSize_tooSmall); - } - if (nbThreads > 1) { - pool = POOL_create(nbThreads, 1); - if (!pool) { - return ERROR(memory_allocation); - } - } - /* Initialization */ - FASTCOVER_best_init(&best); - /* Turn down global display level to clean up display at level 2 and below */ - g_displayLevel = displayLevel == 0 ? 0 : displayLevel - 1; - /* Loop through d first because each new value needs a new context */ - LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n", - kIterations); - for (d = kMinD; d <= kMaxD; d += 2) { - /* Initialize the context for this value of d */ - FASTCOVER_ctx_t ctx; - LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d); - if (!FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f)) { - LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n"); - FASTCOVER_best_destroy(&best); - POOL_free(pool); - return ERROR(GENERIC); - } - /* Loop through k reusing the same context */ - for (k = kMinK; k <= kMaxK; k += kStepSize) { - /* Prepare the arguments */ - FASTCOVER_tryParameters_data_t *data = (FASTCOVER_tryParameters_data_t *)malloc( - sizeof(FASTCOVER_tryParameters_data_t)); - LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k); - if (!data) { - LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n"); - FASTCOVER_best_destroy(&best); - FASTCOVER_ctx_destroy(&ctx); - POOL_free(pool); - return ERROR(GENERIC); - } - data->ctx = &ctx; - data->best = &best; - data->dictBufferCapacity = dictBufferCapacity; - data->parameters = *parameters; - data->parameters.k = k; - data->parameters.d = d; - data->parameters.f = f; - data->parameters.splitPoint = splitPoint; - data->parameters.steps = kSteps; - data->parameters.zParams.notificationLevel = g_displayLevel; - /* Check the parameters */ - if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity)) { - DISPLAYLEVEL(1, "fastCover parameters incorrect\n"); - free(data); - continue; - } - /* Call the function and pass ownership of data to it */ - FASTCOVER_best_start(&best); - if (pool) { - POOL_add(pool, &FASTCOVER_tryParameters, data); - } else { - FASTCOVER_tryParameters(data); - } - /* Print status */ - LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ", - (U32)((iteration * 100) / kIterations)); - ++iteration; - } - FASTCOVER_best_wait(&best); - FASTCOVER_ctx_destroy(&ctx); - } - LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", ""); - /* Fill the output buffer and parameters with output of the best parameters */ - { - const size_t dictSize = best.dictSize; - if (ZSTD_isError(best.compressedSize)) { - const size_t compressedSize = best.compressedSize; - FASTCOVER_best_destroy(&best); - POOL_free(pool); - return compressedSize; - } - *parameters = best.parameters; - memcpy(dictBuffer, best.dict, dictSize); - FASTCOVER_best_destroy(&best); - POOL_free(pool); - return dictSize; - } - -} diff --git a/contrib/experimental_dict_builders/fastCover/fastCover.h b/contrib/experimental_dict_builders/fastCover/fastCover.h deleted file mode 100644 index 958e9f42393..00000000000 --- a/contrib/experimental_dict_builders/fastCover/fastCover.h +++ /dev/null @@ -1,57 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* memset */ -#include /* clock */ -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" -#include "zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" - - -typedef struct { - unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */ - unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */ - unsigned f; /* log of size of frequency array */ - unsigned steps; /* Number of steps : Only used for optimization : 0 means default (32) : Higher means more parameters checked */ - unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ - double splitPoint; /* Percentage of samples used for training: the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (1.0), 1.0 when all samples are used for both training and testing */ - ZDICT_params_t zParams; -} ZDICT_fastCover_params_t; - - -/*! ZDICT_optimizeTrainFromBuffer_fastCover(): - * Train a dictionary from an array of samples using a modified version of the COVER algorithm. - * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, - * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. - * The resulting dictionary will be saved into `dictBuffer`. - * All of the parameters except for f are optional. - * If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8, 10, 12, 14, 16}. - * if steps is zero it defaults to its default value. - * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [16, 2048]. - * - * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - * or an error code, which can be tested with ZDICT_isError(). - * On success `*parameters` contains the parameters selected. - */ - ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, - ZDICT_fastCover_params_t *parameters); - - -/*! ZDICT_trainFromBuffer_fastCover(): - * Train a dictionary from an array of samples using a modified version of the COVER algorithm. - * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, - * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. - * The resulting dictionary will be saved into `dictBuffer`. - * d, k, and f are required. - * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - * or an error code, which can be tested with ZDICT_isError(). - */ -ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, ZDICT_fastCover_params_t parameters); diff --git a/contrib/experimental_dict_builders/fastCover/main.c b/contrib/experimental_dict_builders/fastCover/main.c deleted file mode 100644 index df7d91812e2..00000000000 --- a/contrib/experimental_dict_builders/fastCover/main.c +++ /dev/null @@ -1,183 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* strcmp, strlen */ -#include /* errno */ -#include -#include "fastCover.h" -#include "io.h" -#include "util.h" -#include "zdict.h" - - -/*-************************************* -* Console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - -static const U64 g_refreshRate = SEC_TO_MICRO / 6; -static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; - -#define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \ - if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \ - { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ - if (displayLevel>=4) fflush(stderr); } } } - - -/*-************************************* -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAY("Error %i : ", error); \ - DISPLAY(__VA_ARGS__); \ - DISPLAY("\n"); \ - exit(error); \ -} - - -/*-************************************* -* Constants -***************************************/ -static const unsigned g_defaultMaxDictSize = 110 KB; -#define DEFAULT_CLEVEL 3 - - -/*-************************************* -* FASTCOVER -***************************************/ -int FASTCOVER_trainFromFiles(const char* dictFileName, sampleInfo *info, - unsigned maxDictSize, - ZDICT_fastCover_params_t *params) { - unsigned const displayLevel = params->zParams.notificationLevel; - void* const dictBuffer = malloc(maxDictSize); - - int result = 0; - - /* Checks */ - if (!dictBuffer) - EXM_THROW(12, "not enough memory for trainFromFiles"); /* should not happen */ - - { size_t dictSize; - /* Run the optimize version if either k or d is not provided */ - if (!params->d || !params->k) { - dictSize = ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, params); - } else { - dictSize = ZDICT_trainFromBuffer_fastCover(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *params); - } - DISPLAYLEVEL(2, "k=%u\nd=%u\nf=%u\nsteps=%u\nsplit=%u\n", params->k, params->d, params->f, params->steps, (unsigned)(params->splitPoint*100)); - if (ZDICT_isError(dictSize)) { - DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */ - result = 1; - goto _done; - } - /* save dict */ - DISPLAYLEVEL(2, "Save dictionary of size %u into file %s \n", (U32)dictSize, dictFileName); - saveDict(dictFileName, dictBuffer, dictSize); - } - - /* clean up */ -_done: - free(dictBuffer); - return result; -} - - - -int main(int argCount, const char* argv[]) -{ - int displayLevel = 2; - const char* programName = argv[0]; - int operationResult = 0; - - /* Initialize arguments to default values */ - unsigned k = 0; - unsigned d = 0; - unsigned f = 23; - unsigned steps = 32; - unsigned nbThreads = 1; - unsigned split = 100; - const char* outputFile = "fastCoverDict"; - unsigned dictID = 0; - unsigned maxDictSize = g_defaultMaxDictSize; - - /* Initialize table to store input files */ - const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); - unsigned filenameIdx = 0; - - char* fileNamesBuf = NULL; - unsigned fileNamesNb = filenameIdx; - int followLinks = 0; /* follow directory recursively */ - const char** extendedFileList = NULL; - - /* Parse arguments */ - for (int i = 1; i < argCount; i++) { - const char* argument = argv[i]; - if (longCommandWArg(&argument, "k=")) { k = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "d=")) { d = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "f=")) { f = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "steps=")) { steps = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "split=")) { split = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "dictID=")) { dictID = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "in=")) { - filenameTable[filenameIdx] = argument; - filenameIdx++; - continue; - } - if (longCommandWArg(&argument, "out=")) { - outputFile = argument; - continue; - } - DISPLAYLEVEL(1, "Incorrect parameters\n"); - operationResult = 1; - return operationResult; - } - - /* Get the list of all files recursively (because followLinks==0)*/ - extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, - &fileNamesNb, followLinks); - if (extendedFileList) { - unsigned u; - for (u=0; u /* fprintf */ -#include /* malloc, free, qsort */ -#include /* strcmp, strlen */ -#include /* errno */ -#include -#include "io.h" -#include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ -#include "platform.h" /* Large Files support */ -#include "util.h" -#include "zdict.h" - -/*-************************************* -* Console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - -static const U64 g_refreshRate = SEC_TO_MICRO / 6; -static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; - -#define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \ - if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \ - { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ - if (displayLevel>=4) fflush(stderr); } } } - -/*-************************************* -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAY("Error %i : ", error); \ - DISPLAY(__VA_ARGS__); \ - DISPLAY("\n"); \ - exit(error); \ -} - - -/*-************************************* -* Constants -***************************************/ - -#define SAMPLESIZE_MAX (128 KB) -#define RANDOM_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((U32)-1) : ((U32)1 GB)) -#define RANDOM_MEMMULT 9 -static const size_t g_maxMemory = (sizeof(size_t) == 4) ? - (2 GB - 64 MB) : ((size_t)(512 MB) << sizeof(size_t)); - -#define NOISELENGTH 32 - - -/*-************************************* -* Commandline related functions -***************************************/ -unsigned readU32FromChar(const char** stringPtr){ - const char errorMsg[] = "error: numeric value too large"; - unsigned result = 0; - while ((**stringPtr >='0') && (**stringPtr <='9')) { - unsigned const max = (((unsigned)(-1)) / 10) - 1; - if (result > max) exit(1); - result *= 10, result += **stringPtr - '0', (*stringPtr)++ ; - } - if ((**stringPtr=='K') || (**stringPtr=='M')) { - unsigned const maxK = ((unsigned)(-1)) >> 10; - if (result > maxK) exit(1); - result <<= 10; - if (**stringPtr=='M') { - if (result > maxK) exit(1); - result <<= 10; - } - (*stringPtr)++; /* skip `K` or `M` */ - if (**stringPtr=='i') (*stringPtr)++; - if (**stringPtr=='B') (*stringPtr)++; - } - return result; -} - -unsigned longCommandWArg(const char** stringPtr, const char* longCommand){ - size_t const comSize = strlen(longCommand); - int const result = !strncmp(*stringPtr, longCommand, comSize); - if (result) *stringPtr += comSize; - return result; -} - - -/* ******************************************************** -* File related operations -**********************************************************/ -/** loadFiles() : - * load samples from files listed in fileNamesTable into buffer. - * works even if buffer is too small to load all samples. - * Also provides the size of each sample into sampleSizes table - * which must be sized correctly, using DiB_fileStats(). - * @return : nb of samples effectively loaded into `buffer` - * *bufferSizePtr is modified, it provides the amount data loaded within buffer. - * sampleSizes is filled with the size of each sample. - */ -static unsigned loadFiles(void* buffer, size_t* bufferSizePtr, size_t* sampleSizes, - unsigned sstSize, const char** fileNamesTable, unsigned nbFiles, - size_t targetChunkSize, unsigned displayLevel) { - char* const buff = (char*)buffer; - size_t pos = 0; - unsigned nbLoadedChunks = 0, fileIndex; - - for (fileIndex=0; fileIndex *bufferSizePtr-pos) break; - { size_t const readSize = fread(buff+pos, 1, toLoad, f); - if (readSize != toLoad) EXM_THROW(11, "Pb reading %s", fileName); - pos += readSize; - sampleSizes[nbLoadedChunks++] = toLoad; - remainingToLoad -= targetChunkSize; - if (nbLoadedChunks == sstSize) { /* no more space left in sampleSizes table */ - fileIndex = nbFiles; /* stop there */ - break; - } - if (toLoad < targetChunkSize) { - fseek(f, (long)(targetChunkSize - toLoad), SEEK_CUR); - } } } - fclose(f); - } - DISPLAYLEVEL(2, "\r%79s\r", ""); - *bufferSizePtr = pos; - DISPLAYLEVEL(4, "loaded : %u KB \n", (U32)(pos >> 10)) - return nbLoadedChunks; -} - -#define rotl32(x,r) ((x << r) | (x >> (32 - r))) -static U32 getRand(U32* src) -{ - static const U32 prime1 = 2654435761U; - static const U32 prime2 = 2246822519U; - U32 rand32 = *src; - rand32 *= prime1; - rand32 ^= prime2; - rand32 = rotl32(rand32, 13); - *src = rand32; - return rand32 >> 5; -} - -/* shuffle() : - * shuffle a table of file names in a semi-random way - * It improves dictionary quality by reducing "locality" impact, so if sample set is very large, - * it will load random elements from it, instead of just the first ones. */ -static void shuffle(const char** fileNamesTable, unsigned nbFiles) { - U32 seed = 0xFD2FB528; - unsigned i; - for (i = nbFiles - 1; i > 0; --i) { - unsigned const j = getRand(&seed) % (i + 1); - const char* const tmp = fileNamesTable[j]; - fileNamesTable[j] = fileNamesTable[i]; - fileNamesTable[i] = tmp; - } -} - - -/*-******************************************************** -* Dictionary training functions -**********************************************************/ -size_t findMaxMem(unsigned long long requiredMem) { - size_t const step = 8 MB; - void* testmem = NULL; - - requiredMem = (((requiredMem >> 23) + 1) << 23); - requiredMem += step; - if (requiredMem > g_maxMemory) requiredMem = g_maxMemory; - - while (!testmem) { - testmem = malloc((size_t)requiredMem); - requiredMem -= step; - } - - free(testmem); - return (size_t)requiredMem; -} - -void saveDict(const char* dictFileName, - const void* buff, size_t buffSize) { - FILE* const f = fopen(dictFileName, "wb"); - if (f==NULL) EXM_THROW(3, "cannot open %s ", dictFileName); - - { size_t const n = fwrite(buff, 1, buffSize, f); - if (n!=buffSize) EXM_THROW(4, "%s : write error", dictFileName) } - - { size_t const n = (size_t)fclose(f); - if (n!=0) EXM_THROW(5, "%s : flush error", dictFileName) } -} - -/*! getFileStats() : - * Given a list of files, and a chunkSize (0 == no chunk, whole files) - * provides the amount of data to be loaded and the resulting nb of samples. - * This is useful primarily for allocation purpose => sample buffer, and sample sizes table. - */ -static fileStats getFileStats(const char** fileNamesTable, unsigned nbFiles, - size_t chunkSize, unsigned displayLevel) { - fileStats fs; - unsigned n; - memset(&fs, 0, sizeof(fs)); - for (n=0; n 2*SAMPLESIZE_MAX); - fs.nbSamples += nbSamples; - } - DISPLAYLEVEL(4, "Preparing to load : %u KB \n", (U32)(fs.totalSizeToLoad >> 10)); - return fs; -} - - - - -sampleInfo* getSampleInfo(const char** fileNamesTable, unsigned nbFiles, size_t chunkSize, - unsigned maxDictSize, const unsigned displayLevel) { - fileStats const fs = getFileStats(fileNamesTable, nbFiles, chunkSize, displayLevel); - size_t* const sampleSizes = (size_t*)malloc(fs.nbSamples * sizeof(size_t)); - size_t const memMult = RANDOM_MEMMULT; - size_t const maxMem = findMaxMem(fs.totalSizeToLoad * memMult) / memMult; - size_t loadedSize = (size_t) MIN ((unsigned long long)maxMem, fs.totalSizeToLoad); - void* const srcBuffer = malloc(loadedSize+NOISELENGTH); - - /* Checks */ - if ((!sampleSizes) || (!srcBuffer)) - EXM_THROW(12, "not enough memory for trainFromFiles"); /* should not happen */ - if (fs.oneSampleTooLarge) { - DISPLAYLEVEL(2, "! Warning : some sample(s) are very large \n"); - DISPLAYLEVEL(2, "! Note that dictionary is only useful for small samples. \n"); - DISPLAYLEVEL(2, "! As a consequence, only the first %u bytes of each sample are loaded \n", SAMPLESIZE_MAX); - } - if (fs.nbSamples < 5) { - DISPLAYLEVEL(2, "! Warning : nb of samples too low for proper processing ! \n"); - DISPLAYLEVEL(2, "! Please provide _one file per sample_. \n"); - DISPLAYLEVEL(2, "! Alternatively, split files into fixed-size blocks representative of samples, with -B# \n"); - EXM_THROW(14, "nb of samples too low"); /* we now clearly forbid this case */ - } - if (fs.totalSizeToLoad < (unsigned long long)(8 * maxDictSize)) { - DISPLAYLEVEL(2, "! Warning : data size of samples too small for target dictionary size \n"); - DISPLAYLEVEL(2, "! Samples should be about 100x larger than target dictionary size \n"); - } - - /* init */ - if (loadedSize < fs.totalSizeToLoad) - DISPLAYLEVEL(1, "Not enough memory; training on %u MB only...\n", (unsigned)(loadedSize >> 20)); - - /* Load input buffer */ - DISPLAYLEVEL(3, "Shuffling input files\n"); - shuffle(fileNamesTable, nbFiles); - nbFiles = loadFiles(srcBuffer, &loadedSize, sampleSizes, fs.nbSamples, - fileNamesTable, nbFiles, chunkSize, displayLevel); - - sampleInfo *info = (sampleInfo *)malloc(sizeof(sampleInfo)); - - info->nbSamples = fs.nbSamples; - info->samplesSizes = sampleSizes; - info->srcBuffer = srcBuffer; - - return info; -} - - -void freeSampleInfo(sampleInfo *info) { - if (!info) return; - if (info->samplesSizes) free((void*)(info->samplesSizes)); - if (info->srcBuffer) free((void*)(info->srcBuffer)); - free(info); -} diff --git a/contrib/experimental_dict_builders/randomDictBuilder/io.h b/contrib/experimental_dict_builders/randomDictBuilder/io.h deleted file mode 100644 index 0ee24604eed..00000000000 --- a/contrib/experimental_dict_builders/randomDictBuilder/io.h +++ /dev/null @@ -1,60 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* strcmp, strlen */ -#include /* errno */ -#include -#include "zstd_internal.h" /* includes zstd.h */ -#include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ -#include "platform.h" /* Large Files support */ -#include "util.h" -#include "zdict.h" - - -/*-************************************* -* Structs -***************************************/ -typedef struct { - U64 totalSizeToLoad; - unsigned oneSampleTooLarge; - unsigned nbSamples; -} fileStats; - -typedef struct { - const void* srcBuffer; - const size_t *samplesSizes; - size_t nbSamples; -}sampleInfo; - - - -/*! getSampleInfo(): - * Load from input files and add samples to buffer - * @return: a sampleInfo struct containing infomation about buffer where samples are stored, - * size of each sample, and total number of samples - */ -sampleInfo* getSampleInfo(const char** fileNamesTable, unsigned nbFiles, size_t chunkSize, - unsigned maxDictSize, const unsigned displayLevel); - - - -/*! freeSampleInfo(): - * Free memory allocated for info - */ -void freeSampleInfo(sampleInfo *info); - - - -/*! saveDict(): - * Save data stored on buff to dictFileName - */ -void saveDict(const char* dictFileName, const void* buff, size_t buffSize); - - -unsigned readU32FromChar(const char** stringPtr); - -/** longCommandWArg() : - * check if *stringPtr is the same as longCommand. - * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. - * @return 0 and doesn't modify *stringPtr otherwise. - */ -unsigned longCommandWArg(const char** stringPtr, const char* longCommand); diff --git a/contrib/experimental_dict_builders/randomDictBuilder/main.c b/contrib/experimental_dict_builders/randomDictBuilder/main.c deleted file mode 100644 index 3ad88574609..00000000000 --- a/contrib/experimental_dict_builders/randomDictBuilder/main.c +++ /dev/null @@ -1,161 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* strcmp, strlen */ -#include /* errno */ -#include -#include "random.h" -#include "io.h" -#include "util.h" -#include "zdict.h" - - -/*-************************************* -* Console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - -static const U64 g_refreshRate = SEC_TO_MICRO / 6; -static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; - -#define DISPLAYUPDATE(l, ...) { if (displayLevel>=l) { \ - if ((UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) || (displayLevel>=4)) \ - { g_displayClock = UTIL_getTime(); DISPLAY(__VA_ARGS__); \ - if (displayLevel>=4) fflush(stderr); } } } - - -/*-************************************* -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAY("Error %i : ", error); \ - DISPLAY(__VA_ARGS__); \ - DISPLAY("\n"); \ - exit(error); \ -} - - -/*-************************************* -* Constants -***************************************/ -static const unsigned g_defaultMaxDictSize = 110 KB; -#define DEFAULT_CLEVEL 3 -#define DEFAULT_k 200 -#define DEFAULT_OUTPUTFILE "defaultDict" -#define DEFAULT_DICTID 0 - - - -/*-************************************* -* RANDOM -***************************************/ -int RANDOM_trainFromFiles(const char* dictFileName, sampleInfo *info, - unsigned maxDictSize, - ZDICT_random_params_t *params) { - unsigned const displayLevel = params->zParams.notificationLevel; - void* const dictBuffer = malloc(maxDictSize); - - int result = 0; - - /* Checks */ - if (!dictBuffer) - EXM_THROW(12, "not enough memory for trainFromFiles"); /* should not happen */ - - { size_t dictSize; - dictSize = ZDICT_trainFromBuffer_random(dictBuffer, maxDictSize, info->srcBuffer, - info->samplesSizes, info->nbSamples, *params); - DISPLAYLEVEL(2, "k=%u\n", params->k); - if (ZDICT_isError(dictSize)) { - DISPLAYLEVEL(1, "dictionary training failed : %s \n", ZDICT_getErrorName(dictSize)); /* should not happen */ - result = 1; - goto _done; - } - /* save dict */ - DISPLAYLEVEL(2, "Save dictionary of size %u into file %s \n", (U32)dictSize, dictFileName); - saveDict(dictFileName, dictBuffer, dictSize); - } - - /* clean up */ -_done: - free(dictBuffer); - return result; -} - - - -int main(int argCount, const char* argv[]) -{ - int displayLevel = 2; - const char* programName = argv[0]; - int operationResult = 0; - - /* Initialize arguments to default values */ - unsigned k = DEFAULT_k; - const char* outputFile = DEFAULT_OUTPUTFILE; - unsigned dictID = DEFAULT_DICTID; - unsigned maxDictSize = g_defaultMaxDictSize; - - /* Initialize table to store input files */ - const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); - unsigned filenameIdx = 0; - - /* Parse arguments */ - for (int i = 1; i < argCount; i++) { - const char* argument = argv[i]; - if (longCommandWArg(&argument, "k=")) { k = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "dictID=")) { dictID = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "in=")) { - filenameTable[filenameIdx] = argument; - filenameIdx++; - continue; - } - if (longCommandWArg(&argument, "out=")) { - outputFile = argument; - continue; - } - DISPLAYLEVEL(1, "Incorrect parameters\n"); - operationResult = 1; - return operationResult; - } - - char* fileNamesBuf = NULL; - unsigned fileNamesNb = filenameIdx; - int followLinks = 0; /* follow directory recursively */ - const char** extendedFileList = NULL; - extendedFileList = UTIL_createFileList(filenameTable, filenameIdx, &fileNamesBuf, - &fileNamesNb, followLinks); - if (extendedFileList) { - unsigned u; - for (u=0; u /* fprintf */ -#include /* malloc, free, qsort */ -#include /* memset */ -#include /* clock */ -#include "random.h" -#include "util.h" /* UTIL_getFileSize, UTIL_getTotalFileSize */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" - -/*-************************************* -* Console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - -#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ - if (displayLevel >= l) { \ - if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \ - g_time = clock(); \ - DISPLAY(__VA_ARGS__); \ - } \ - } -#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(displayLevel, l, __VA_ARGS__) -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; - - - -/* ******************************************************** -* Random Dictionary Builder -**********************************************************/ -/** - * Returns the sum of the sample sizes. - */ -static size_t RANDOM_sum(const size_t *samplesSizes, unsigned nbSamples) { - size_t sum = 0; - unsigned i; - for (i = 0; i < nbSamples; ++i) { - sum += samplesSizes[i]; - } - return sum; -} - - -/** - * A segment is an inclusive range in the source. - */ -typedef struct { - U32 begin; - U32 end; -} RANDOM_segment_t; - - -/** - * Selects a random segment from totalSamplesSize - k + 1 possible segments - */ -static RANDOM_segment_t RANDOM_selectSegment(const size_t totalSamplesSize, - ZDICT_random_params_t parameters) { - const U32 k = parameters.k; - RANDOM_segment_t segment; - unsigned index; - - /* Randomly generate a number from 0 to sampleSizes - k */ - index = rand()%(totalSamplesSize - k + 1); - - /* inclusive */ - segment.begin = index; - segment.end = index + k - 1; - - return segment; -} - - -/** - * Check the validity of the parameters. - * Returns non-zero if the parameters are valid and 0 otherwise. - */ -static int RANDOM_checkParameters(ZDICT_random_params_t parameters, - size_t maxDictSize) { - /* k is a required parameter */ - if (parameters.k == 0) { - return 0; - } - /* k <= maxDictSize */ - if (parameters.k > maxDictSize) { - return 0; - } - return 1; -} - - -/** - * Given the prepared context build the dictionary. - */ -static size_t RANDOM_buildDictionary(const size_t totalSamplesSize, const BYTE *samples, - void *dictBuffer, size_t dictBufferCapacity, - ZDICT_random_params_t parameters) { - BYTE *const dict = (BYTE *)dictBuffer; - size_t tail = dictBufferCapacity; - const int displayLevel = parameters.zParams.notificationLevel; - while (tail > 0) { - - /* Select a segment */ - RANDOM_segment_t segment = RANDOM_selectSegment(totalSamplesSize, parameters); - - size_t segmentSize; - segmentSize = MIN(segment.end - segment.begin + 1, tail); - - tail -= segmentSize; - memcpy(dict + tail, samples + segment.begin, segmentSize); - DISPLAYUPDATE( - 2, "\r%u%% ", - (U32)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity)); - } - - return tail; -} - - - - -ZDICTLIB_API size_t ZDICT_trainFromBuffer_random( - void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_random_params_t parameters) { - const int displayLevel = parameters.zParams.notificationLevel; - BYTE* const dict = (BYTE*)dictBuffer; - /* Checks */ - if (!RANDOM_checkParameters(parameters, dictBufferCapacity)) { - DISPLAYLEVEL(1, "k is incorrect\n"); - return ERROR(GENERIC); - } - if (nbSamples == 0) { - DISPLAYLEVEL(1, "Random must have at least one input file\n"); - return ERROR(GENERIC); - } - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { - DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", - ZDICT_DICTSIZE_MIN); - return ERROR(dstSize_tooSmall); - } - const size_t totalSamplesSize = RANDOM_sum(samplesSizes, nbSamples); - const BYTE *const samples = (const BYTE *)samplesBuffer; - - DISPLAYLEVEL(2, "Building dictionary\n"); - { - const size_t tail = RANDOM_buildDictionary(totalSamplesSize, samples, - dictBuffer, dictBufferCapacity, parameters); - const size_t dictSize = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - samplesBuffer, samplesSizes, nbSamples, parameters.zParams); - if (!ZSTD_isError(dictSize)) { - DISPLAYLEVEL(2, "Constructed dictionary of size %u\n", - (U32)dictSize); - } - return dictSize; - } -} diff --git a/contrib/experimental_dict_builders/randomDictBuilder/random.h b/contrib/experimental_dict_builders/randomDictBuilder/random.h deleted file mode 100644 index 352775f950c..00000000000 --- a/contrib/experimental_dict_builders/randomDictBuilder/random.h +++ /dev/null @@ -1,29 +0,0 @@ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* memset */ -#include /* clock */ -#include "zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" - - - -typedef struct { - unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+]; Default to 200 */ - ZDICT_params_t zParams; -} ZDICT_random_params_t; - - -/*! ZDICT_trainFromBuffer_random(): - * Train a dictionary from an array of samples. - * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, - * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. - * The resulting dictionary will be saved into `dictBuffer`. - * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - * or an error code, which can be tested with ZDICT_isError(). - */ -ZDICTLIB_API size_t ZDICT_trainFromBuffer_random( void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_random_params_t parameters); diff --git a/contrib/experimental_dict_builders/randomDictBuilder/test.sh b/contrib/experimental_dict_builders/randomDictBuilder/test.sh deleted file mode 100644 index 1eb732e52a0..00000000000 --- a/contrib/experimental_dict_builders/randomDictBuilder/test.sh +++ /dev/null @@ -1,14 +0,0 @@ -echo "Building random dictionary with in=../../lib/common k=200 out=dict1" -./main in=../../../lib/common k=200 out=dict1 -zstd -be3 -D dict1 -r ../../../lib/common -q -echo "Building random dictionary with in=../../lib/common k=500 out=dict2 dictID=100 maxdict=140000" -./main in=../../../lib/common k=500 out=dict2 dictID=100 maxdict=140000 -zstd -be3 -D dict2 -r ../../../lib/common -q -echo "Building random dictionary with 2 sample sources" -./main in=../../../lib/common in=../../../lib/compress out=dict3 -zstd -be3 -D dict3 -r ../../../lib/common -q -echo "Removing dict1 dict2 dict3" -rm -f dict1 dict2 dict3 - -echo "Testing with invalid parameters, should fail" -! ./main r=10 From aea2ff5d8d35baf2398cab8e76205e6df3cdcc24 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 14:56:21 -0800 Subject: [PATCH 046/402] fixed wrong assert() in regression driver --- tests/fuzz/regression_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzz/regression_driver.c b/tests/fuzz/regression_driver.c index e91ef0def7e..e875cf6ea9c 100644 --- a/tests/fuzz/regression_driver.c +++ b/tests/fuzz/regression_driver.c @@ -32,8 +32,8 @@ int main(int argc, char const **argv) { #else files = UTIL_createFNT_fromROTable(fnTable, numFiles); if (!files) numFiles = 0; + assert(numFiles == files->tableSize); #endif - if (files) assert(numFiles == files->tableSize); if (numFiles == 0) fprintf(stderr, "WARNING: No files passed to %s\n", argv[0]); for (i = 0; i < numFiles; ++i) { From be34969e5cf4b019d29d284c5dc32302b308b2b2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 15:07:35 -0800 Subject: [PATCH 047/402] minor man page fix --- programs/zstd.1 | 4 ++-- programs/zstd.1.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/zstd.1 b/programs/zstd.1 index b5b4134c043..1ff655d173d 100644 --- a/programs/zstd.1 +++ b/programs/zstd.1 @@ -1,5 +1,5 @@ . -.TH "ZSTD" "1" "October 2019" "zstd 1.4.4" "User Commands" +.TH "ZSTD" "1" "November 2019" "zstd 1.4.4" "User Commands" . .SH "NAME" \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files @@ -156,7 +156,7 @@ Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \ \fB\-r\fR: operate recursively on directories . .IP "\(bu" 4 -\fB\-\-filelist=FILE\fR read a list of files to process as content from \fBFILE\fR\. Format is compatible with \fBls\fR output, with one file per file\. +\fB\-\-filelist=FILE\fR read a list of files to process as content from \fBFILE\fR\. Format is compatible with \fBls\fR output, with one file per line\. . .IP "\(bu" 4 \fB\-\-output\-dir\-flat[=dir]\fR: resulting files are stored into target \fBdir\fR directory, instead of same directory as origin file\. Be aware that this command can introduce name collision issues, if multiple files, from different directories, end up having the same name\. Collision resolution ensures first file with a given name will be present in \fBdir\fR, while in combination with \fB\-f\fR, the last file will be present instead\. diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 50dc7c8f9e4..edb5ea0a963 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -193,7 +193,7 @@ the last one takes effect. operate recursively on directories * `--filelist=FILE` read a list of files to process as content from `FILE`. - Format is compatible with `ls` output, with one file per file. + Format is compatible with `ls` output, with one file per line. * `--output-dir-flat[=dir]`: resulting files are stored into target `dir` directory, instead of same directory as origin file. From 9df49dc50a1c34d2cc25929af379986e88faaab7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 15:23:44 -0800 Subject: [PATCH 048/402] Visual compiler bug work-around --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 769ec8b73b8..7839799da5b 100644 --- a/programs/util.c +++ b/programs/util.c @@ -647,7 +647,7 @@ FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFile size_t const sizeof_FNTable = nbFilenames * sizeof(*filenames); const char** const newFNTable = (const char**)malloc(sizeof_FNTable); if (newFNTable==NULL) return NULL; - memcpy(newFNTable, filenames, sizeof_FNTable); + memcpy((void*)newFNTable, filenames, sizeof_FNTable); /* void* : mitigate a Visual compiler bug or limitation */ return UTIL_createFileNamesTable(newFNTable, nbFilenames, NULL); } From 2ed5344e84df9daa2ca5abbc7aa88aea495a724f Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 6 Nov 2019 15:46:58 -0800 Subject: [PATCH 049/402] added target zstd-dictBuilder check that the dictBuilder can be compiled with only lib/common and lib/compress as dependencies. --- programs/.gitignore | 1 + programs/Makefile | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/programs/.gitignore b/programs/.gitignore index 0a8e18fbb2f..662f708399f 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -7,6 +7,7 @@ zstd-decompress zstd-frugal zstd-small zstd-nolegacy +zstd-dictBuilder # Object files *.o diff --git a/programs/Makefile b/programs/Makefile index 64dcae0028e..37d4a95e8ec 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -158,7 +158,7 @@ default: zstd-release all: zstd .PHONY: allVariants -allVariants: zstd zstd-compress zstd-decompress zstd-small zstd-nolegacy +allVariants: zstd zstd-compress zstd-decompress zstd-small zstd-nolegacy zstd-dictBuilder $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP) @@ -231,6 +231,10 @@ zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT) +zstd-dictBuilder: CPPFLAGS += -DZSTD_NOBENCH -DZSTD_NODECOMPRESS +zstd-dictBuilder: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) $(ZDICT_FILES) zstdcli.c util.c timefn.c fileio.c dibio.c + $(CC) $(FLAGS) $^ -o $@$(EXT) + zstdmt: zstd ln -sf zstd zstdmt @@ -245,7 +249,7 @@ clean: @$(RM) core *.o tmp* result* *.gcda dictionary *.zst \ zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \ zstd-small$(EXT) zstd-frugal$(EXT) zstd-nolegacy$(EXT) zstd4$(EXT) \ - *.gcda default.profraw have_zlib$(EXT) + zstd-dictBuilder$(EXT) *.gcda default.profraw have_zlib$(EXT) @echo Cleaning completed MD2ROFF = ronn From 8c474f98456ee4cb7540b479816c60399cb6685c Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 6 Nov 2019 17:41:29 -0800 Subject: [PATCH 050/402] Fix parameter selection and adjustment with srcSize == 0 --- lib/compress/zstd_compress.c | 75 ++++++++++++++++++--------- lib/compress/zstd_compress_internal.h | 1 + lib/compress/zstdmt_compress.c | 2 +- tests/fuzzer.c | 22 ++++++++ 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9299b07546b..a2c046ec767 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -850,7 +850,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) { ZSTD_localDict* const dl = &cctx->localDict; ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, 0, dl->dictSize); + &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize); if (dl->dict == NULL) { /* No local dictionary. */ assert(dl->dictBuffer == NULL); @@ -1011,7 +1011,7 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) * optimize `cPar` for a specified input (`srcSize` and `dictSize`). * mostly downsize to reduce memory consumption and initialization latency. * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known. - * note : for the time being, `srcSize==0` means "unknown" too, for compatibility with older convention. + * note : `srcSize==0` means 0! * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ static ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, @@ -1022,10 +1022,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); assert(ZSTD_checkCParams(cPar)==0); - if (dictSize && (srcSize+1<2) /* ZSTD_CONTENTSIZE_UNKNOWN and 0 mean "unknown" */ ) - srcSize = minSrcSize; /* presumed small when there is a dictionary */ - else if (srcSize == 0) - srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */ + if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) + srcSize = minSrcSize; /* resize windowLog if input is small enough, to use less memory */ if ( (srcSize < maxWindowResize) @@ -1054,9 +1052,13 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, size_t dictSize) { cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ + if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); } +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); + ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize) { @@ -1064,7 +1066,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { srcSizeHint = CCtxParams->srcSizeHint; } - cParams = ZSTD_getCParams(CCtxParams->compressionLevel, srcSizeHint, dictSize); + cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize); if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog; if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog; @@ -1074,6 +1076,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength; if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy; assert(!ZSTD_checkCParams(cParams)); + /* srcSizeHint == 0 means 0 */ return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize); } @@ -1109,7 +1112,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) { RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, 0, 0); + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); U32 const divider = (cParams.minMatch==3) ? 3 : 4; size_t const maxNbSeq = blockSize / divider; @@ -1141,7 +1144,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); return ZSTD_estimateCCtxSize_usingCParams(cParams); } @@ -1160,7 +1163,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, 0, 0); + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; @@ -1180,7 +1183,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); return ZSTD_estimateCStreamSize_usingCParams(cParams); } @@ -1608,6 +1611,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, assert(windowLog != 0); /* Resize working context table params for input only, since the dict * has its own tables. */ + /* pledgeSrcSize == 0 means 0! */ params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); params.cParams.windowLog = windowLog; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, @@ -3000,7 +3004,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); @@ -3134,7 +3138,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, srcSize + (!srcSize), dict ? dictSize : 0); + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0); ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); assert(params.fParams.contentSizeFlag == 1); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams); @@ -3181,7 +3185,7 @@ size_t ZSTD_estimateCDictSize_advanced( size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); } @@ -3292,7 +3296,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize); + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); @@ -3303,7 +3307,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize); + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); return ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); @@ -4074,35 +4078,56 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV }, }; -/*! ZSTD_getCParams() : +/*! ZSTD_getCParams_internal() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. - * Size values are optional, provide 0 if not known or unused */ -ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) + * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. + * Use dictSize == 0 for unknown or unused. */ +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { - size_t const addedSize = srcSizeHint ? 0 : 500; - U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : ZSTD_CONTENTSIZE_UNKNOWN; /* intentional overflow for srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN */ + int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; + size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; + U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); int row = compressionLevel; - DEBUGLOG(5, "ZSTD_getCParams (cLevel=%i)", compressionLevel); + DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ - return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); /* refine parameters based on srcSize & dictSize */ + /* refine parameters based on srcSize & dictSize */ + return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); } } +/*! ZSTD_getCParams() : + * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. + * Size values are optional, provide 0 if not known or unused */ +ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) +{ + if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; + return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); +} + /*! ZSTD_getParams() : * same idea as ZSTD_getCParams() * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). * Fields of `ZSTD_frameParameters` are set to default values */ -ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); memset(¶ms, 0, sizeof(params)); params.cParams = cParams; params.fParams.contentSizeFlag = 1; return params; } + +/*! ZSTD_getParams() : + * same idea as ZSTD_getCParams() + * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). + * Fields of `ZSTD_frameParameters` are set to default values */ +ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { + if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; + return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize); +} diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 14036f873f5..4ed09890e45 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -940,6 +940,7 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) /* ZSTD_getCParamsFromCCtxParams() : * cParams are built depending on compressionLevel, src size hints, * LDM and manually set compression parameters. + * Note: srcSizeHint == 0 means 0! */ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize); diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index bc3062b5309..b580d94511c 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1076,7 +1076,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, 0, 0); + { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0); cParams.windowLog = saved_wlog; mtctx->params.cParams = cParams; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 88f3b83f834..65dc6f50aa0 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -884,6 +884,28 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTDMT_freeCCtx(mtctx); } + DISPLAYLEVEL(3, "test%3u : compress empty string and decompress with small window log : ", testNb++); + { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + char out[32]; + if (cctx == NULL || dctx == NULL) goto _output_error; + CHECK( ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0) ); + CHECK_VAR(cSize, ZSTD_compress2(cctx, out, sizeof(out), NULL, 0) ); + DISPLAYLEVEL(3, "OK (%u bytes)\n", (unsigned)cSize); + + CHECK( ZSTD_DCtx_setParameter(dctx, ZSTD_d_windowLogMax, 10) ); + { char const* outPtr = out; + ZSTD_inBuffer inBuffer = { outPtr, cSize, 0 }; + ZSTD_outBuffer outBuffer = { NULL, 0, 0 }; + size_t dSize; + CHECK_VAR(dSize, ZSTD_decompressStream(dctx, &outBuffer, &inBuffer) ); + if (dSize != 0) goto _output_error; + } + + ZSTD_freeDCtx(dctx); + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "test%3i : compress -T2 with/without literals compression : ", testNb++) { ZSTD_CCtx* cctx = ZSTD_createCCtx(); size_t cSize1, cSize2; From 6ddb783c3edf532be14f60277d57977cbadd78cb Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Thu, 7 Nov 2019 11:01:13 -0600 Subject: [PATCH 051/402] Change c90 to c89 c89 and c90 are the same language. Old compilers like gcc 4.2.1 don't know the c90 alias. --- Makefile | 4 ++-- zlibWrapper/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index efb555c35b3..8ff9642f1cc 100644 --- a/Makefile +++ b/Makefile @@ -351,9 +351,9 @@ cmakebuild: mkdir $(BUILDIR)/cmake/build cd $(BUILDIR)/cmake/build ; cmake -DCMAKE_INSTALL_PREFIX:PATH=~/install_test_dir $(CMAKE_PARAMS) .. ; $(MAKE) install ; $(MAKE) uninstall -c90build: clean +c89build: clean $(CC) -v - CFLAGS="-std=c90 -Werror" $(MAKE) allmost # will fail, due to missing support for `long long` + CFLAGS="-std=c89 -Werror" $(MAKE) allmost # will fail, due to missing support for `long long` gnu90build: clean $(CC) -v diff --git a/zlibWrapper/Makefile b/zlibWrapper/Makefile index 6addb743cbe..feed5b84a34 100644 --- a/zlibWrapper/Makefile +++ b/zlibWrapper/Makefile @@ -20,8 +20,8 @@ TEST_FILE = ../doc/zstd_compression_format.md CPPFLAGS += -DXXH_NAMESPACE=ZSTD_ -I$(ZLIB_PATH) -I$(PROGRAMS_PATH) \ -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZLIBWRAPPER_PATH) -STDFLAGS = -std=c90 -pedantic -Wno-long-long -Wno-variadic-macros -Wc++-compat \ - -DNO_snprintf -DNO_vsnprintf # strict ISO C90 is missing these prototypes +STDFLAGS = -std=c89 -pedantic -Wno-long-long -Wno-variadic-macros -Wc++-compat \ + -DNO_snprintf -DNO_vsnprintf # strict ANSI C89 is missing these prototypes DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum \ -Wdeclaration-after-statement -Wstrict-prototypes -Wundef \ -Wstrict-aliasing=1 From 3c36a7f13aa8ec698e044b623ef8d2c3624a0030 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Tue, 29 Oct 2019 16:45:11 -0400 Subject: [PATCH 052/402] Add ZDICT_getHeaderSize() --- lib/dictBuilder/zdict.c | 12 ++++++++++++ lib/dictBuilder/zdict.h | 1 + 2 files changed, 13 insertions(+) diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 1e7f8343209..863a8edf77a 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -48,6 +48,7 @@ # define ZDICT_STATIC_LINKING_ONLY #endif #include "zdict.h" +#include "decompress/zstd_decompress_internal.h" /* ZSTD_entropyDTables_t */ /*-************************************* @@ -99,6 +100,17 @@ unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize) return MEM_readLE32((const char*)dictBuffer + 4); } +size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) +{ + if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0; + + { ZSTD_entropyDTables_t dummyEntropyTables; + size_t headerSize; + dummyEntropyTables.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); + headerSize = ZSTD_loadDEntropy(&dummyEntropyTables, dictBuffer, dictSize); + return ZSTD_isError(headerSize) ? 0 : headerSize; + } +} /*-******************************************************** * Dictionary training functions diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index 37978ecdfb8..f16d573a916 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -64,6 +64,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap /*====== Helper functions ======*/ ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ +ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns zero if error (not a valid dictionary) */ ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); From e1edc554a36fc4e3d006fe456a4799b8513202c0 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Sun, 3 Nov 2019 17:44:28 -0500 Subject: [PATCH 053/402] Added 2 unit tests: one for sanity, one for correctnesson fixed dict --- tests/fuzzer.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 88f3b83f834..9be92471e33 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1137,6 +1137,7 @@ static int basicUnitTests(U32 const seed, double compressibility) size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t)); size_t dictSize; U32 dictID; + U32 dictHeaderSize; if (dictBuffer==NULL || samplesSizes==NULL) { free(dictBuffer); @@ -1226,6 +1227,29 @@ static int basicUnitTests(U32 const seed, double compressibility) if (dictID==0) goto _output_error; DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictID); + DISPLAYLEVEL(3, "test%3i : check dict header size no error : ", testNb++); + dictHeaderSize = ZDICT_getDictHeaderSize(dictBuffer, dictSize); + if (dictHeaderSize==0) goto _output_error; + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictHeaderSize); + + DISPLAYLEVEL(3, "test%3i : check dict header size correctness : ", testNb++); + { unsigned char const dictBufferFixed[144] = { 0x37, 0xa4, 0x30, 0xec, 0x63, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x1f, + 0x0f, 0x00, 0x28, 0xe5, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x0f, 0x9e, 0x0f, 0x00, 0x00, 0x24, 0x40, 0x80, 0x00, 0x01, + 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xde, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0xbc, 0xe1, 0x4b, 0x92, 0x0e, 0xb4, 0x7b, 0x18, + 0x86, 0x61, 0x18, 0xc6, 0x18, 0x63, 0x8c, 0x31, 0xc6, 0x18, 0x63, 0x8c, + 0x31, 0x66, 0x66, 0x66, 0x66, 0xb6, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x73, 0x6f, 0x64, 0x61, + 0x6c, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x72, 0x74, 0x6f, 0x72, 0x20, 0x65, + 0x6c, 0x65, 0x69, 0x66, 0x65, 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6c, 0x69 }; + dictHeaderSize = ZDICT_getDictHeaderSize(dictBufferFixed, 144); + if (dictHeaderSize != 115) goto _output_error; + } + DISPLAYLEVEL(3, "OK : %u \n", (unsigned)dictHeaderSize); + DISPLAYLEVEL(3, "test%3i : compress with dictionary : ", testNb++); cSize = ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, From 97b7f712f3590bf6b81d2211c6a5f65f81b22ae4 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Mon, 4 Nov 2019 14:33:52 -0500 Subject: [PATCH 054/402] Change to heap allocation, remove implicit type conversion --- lib/dictBuilder/zdict.c | 9 +++++---- tests/fuzzer.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 863a8edf77a..32f86366082 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -104,10 +104,11 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0; - { ZSTD_entropyDTables_t dummyEntropyTables; - size_t headerSize; - dummyEntropyTables.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); - headerSize = ZSTD_loadDEntropy(&dummyEntropyTables, dictBuffer, dictSize); + { size_t headerSize; + ZSTD_entropyDTables_t* dummyEntropyTables = (ZSTD_entropyDTables_t*)malloc(sizeof(ZSTD_entropyDTables_t)); + dummyEntropyTables->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); + headerSize = ZSTD_loadDEntropy(dummyEntropyTables, dictBuffer, dictSize); + free(dummyEntropyTables); return ZSTD_isError(headerSize) ? 0 : headerSize; } } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 9be92471e33..9a05daab7ad 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1137,7 +1137,7 @@ static int basicUnitTests(U32 const seed, double compressibility) size_t* const samplesSizes = (size_t*) malloc(nbSamples * sizeof(size_t)); size_t dictSize; U32 dictID; - U32 dictHeaderSize; + size_t dictHeaderSize; if (dictBuffer==NULL || samplesSizes==NULL) { free(dictBuffer); From 341e0641ed5ebc1b3ac9695b28e2b711408fadbc Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Mon, 4 Nov 2019 16:13:52 -0500 Subject: [PATCH 055/402] Checks malloc() for failure, returns 0 if so --- lib/dictBuilder/zdict.c | 3 +++ lib/dictBuilder/zdict.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 32f86366082..6db57b1448c 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -106,6 +106,9 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { size_t headerSize; ZSTD_entropyDTables_t* dummyEntropyTables = (ZSTD_entropyDTables_t*)malloc(sizeof(ZSTD_entropyDTables_t)); + if (!dummyEntropyTables) { + return 0; + } dummyEntropyTables->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); headerSize = ZSTD_loadDEntropy(dummyEntropyTables, dictBuffer, dictSize); free(dummyEntropyTables); diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index f16d573a916..bb89f1f9f9d 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -64,7 +64,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap /*====== Helper functions ======*/ ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ -ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns zero if error (not a valid dictionary) */ +ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns zero if error (not a valid dictionary or mem alloc failure) */ ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); From 84404cff6efc767dcce0833d4a9eb9c742ad2301 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Tue, 5 Nov 2019 15:07:07 -0500 Subject: [PATCH 056/402] Move decompress symbols into zstd_internal.h, remove dependency --- lib/common/zstd_internal.h | 28 +++++++++++++++++++++++ lib/decompress/zstd_decompress_internal.h | 23 ------------------- lib/dictBuilder/zdict.c | 2 +- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index dcdcbdb81cd..db3ce1fc10f 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -251,6 +251,34 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e /*-******************************************* * Private declarations *********************************************/ +/** + * ZSTD_seqSymbol, ZSTD_entropyDTables_t, ZSTD_loadDEntropy(), and SEQSYMBOL_TABLE_SIZE() + * are used by ZDICT_getDictHeaderSize() and various functions in zstd_decompress.h + */ + + typedef struct { + U16 nextState; + BYTE nbAdditionalBits; + BYTE nbBits; + U32 baseValue; + } ZSTD_seqSymbol; + +#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) + +typedef struct { + ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ + ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ + ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ + HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ + U32 rep[ZSTD_REP_NUM]; +} ZSTD_entropyDTables_t; + +/*! ZSTD_loadDEntropy() : + * dict : must point at beginning of a valid zstd dictionary. + * @return : size of entropy tables read (includes 8-byte magic number and dictionary ID) */ +size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, + const void* const dict, size_t const dictSize); + typedef struct seqDef_s { U32 offset; U16 litLength; diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index ccbdfa090fa..1a71e23643c 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -64,23 +64,6 @@ static const U32 ML_base[MaxML+1] = { U32 tableLog; } ZSTD_seqSymbol_header; - typedef struct { - U16 nextState; - BYTE nbAdditionalBits; - BYTE nbBits; - U32 baseValue; - } ZSTD_seqSymbol; - - #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) - -typedef struct { - ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ - ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ - ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ - HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ - U32 rep[ZSTD_REP_NUM]; -} ZSTD_entropyDTables_t; - typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock, ZSTDds_decompressLastBlock, ZSTDds_checkChecksum, @@ -158,12 +141,6 @@ struct ZSTD_DCtx_s * Shared internal functions *********************************************************/ -/*! ZSTD_loadDEntropy() : - * dict : must point at beginning of a valid zstd dictionary. - * @return : size of entropy tables read */ -size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, - const void* const dict, size_t const dictSize); - /*! ZSTD_checkContinuity() : * check if next `dst` follows previous position, where decompression ended. * If yes, do nothing (continue on current segment). diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6db57b1448c..7ea0a2d4832 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -48,7 +48,6 @@ # define ZDICT_STATIC_LINKING_ONLY #endif #include "zdict.h" -#include "decompress/zstd_decompress_internal.h" /* ZSTD_entropyDTables_t */ /*-************************************* @@ -109,6 +108,7 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) if (!dummyEntropyTables) { return 0; } + dummyEntropyTables->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); headerSize = ZSTD_loadDEntropy(dummyEntropyTables, dictBuffer, dictSize); free(dummyEntropyTables); From 4b141b63e009eeaf3d6d2624e3a9a81692f40ebb Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 09:29:15 -0500 Subject: [PATCH 057/402] Revert "Move decompress symbols into zstd_internal.h, remove dependency" This reverts commit a152b4c67a5266f611db4a2eac4a79003852a795. --- lib/common/zstd_internal.h | 28 ----------------------- lib/decompress/zstd_decompress_internal.h | 23 +++++++++++++++++++ lib/dictBuilder/zdict.c | 2 +- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index db3ce1fc10f..dcdcbdb81cd 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -251,34 +251,6 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e /*-******************************************* * Private declarations *********************************************/ -/** - * ZSTD_seqSymbol, ZSTD_entropyDTables_t, ZSTD_loadDEntropy(), and SEQSYMBOL_TABLE_SIZE() - * are used by ZDICT_getDictHeaderSize() and various functions in zstd_decompress.h - */ - - typedef struct { - U16 nextState; - BYTE nbAdditionalBits; - BYTE nbBits; - U32 baseValue; - } ZSTD_seqSymbol; - -#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) - -typedef struct { - ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ - ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ - ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ - HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ - U32 rep[ZSTD_REP_NUM]; -} ZSTD_entropyDTables_t; - -/*! ZSTD_loadDEntropy() : - * dict : must point at beginning of a valid zstd dictionary. - * @return : size of entropy tables read (includes 8-byte magic number and dictionary ID) */ -size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, - const void* const dict, size_t const dictSize); - typedef struct seqDef_s { U32 offset; U16 litLength; diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 1a71e23643c..ccbdfa090fa 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -64,6 +64,23 @@ static const U32 ML_base[MaxML+1] = { U32 tableLog; } ZSTD_seqSymbol_header; + typedef struct { + U16 nextState; + BYTE nbAdditionalBits; + BYTE nbBits; + U32 baseValue; + } ZSTD_seqSymbol; + + #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) + +typedef struct { + ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ + ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ + ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ + HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ + U32 rep[ZSTD_REP_NUM]; +} ZSTD_entropyDTables_t; + typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock, ZSTDds_decompressLastBlock, ZSTDds_checkChecksum, @@ -141,6 +158,12 @@ struct ZSTD_DCtx_s * Shared internal functions *********************************************************/ +/*! ZSTD_loadDEntropy() : + * dict : must point at beginning of a valid zstd dictionary. + * @return : size of entropy tables read */ +size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, + const void* const dict, size_t const dictSize); + /*! ZSTD_checkContinuity() : * check if next `dst` follows previous position, where decompression ended. * If yes, do nothing (continue on current segment). diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 7ea0a2d4832..6db57b1448c 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -48,6 +48,7 @@ # define ZDICT_STATIC_LINKING_ONLY #endif #include "zdict.h" +#include "decompress/zstd_decompress_internal.h" /* ZSTD_entropyDTables_t */ /*-************************************* @@ -108,7 +109,6 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) if (!dummyEntropyTables) { return 0; } - dummyEntropyTables->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); headerSize = ZSTD_loadDEntropy(dummyEntropyTables, dictBuffer, dictSize); free(dummyEntropyTables); From 0bcaf6db089d529ce7cb73c0511dace1e8d3be8b Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 10:43:43 -0500 Subject: [PATCH 058/402] First working pass at refactor of loadZstdDictionary() --- lib/compress/zstd_compress.c | 72 ++++++++++++++++----------- lib/compress/zstd_compress_internal.h | 12 ++++- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9299b07546b..0ebbf1926ac 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2768,37 +2768,12 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym return 0; } - -/* Dictionary format : - * See : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format - */ -/*! ZSTD_loadZstdDictionary() : - * @return : dictID, or an error code - * assumptions : magic number supposed already checked - * dictSize supposed >= 8 - */ -static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, - ZSTD_matchState_t* ms, - ZSTD_cwksp* ws, - ZSTD_CCtx_params const* params, - const void* dict, size_t dictSize, - ZSTD_dictTableLoadMethod_e dtlm, - void* workspace) +size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, + short* offcodeNCount, unsigned* offcodeMaxValue, + const void* const dict, size_t dictSize) { const BYTE* dictPtr = (const BYTE*)dict; - const BYTE* const dictEnd = dictPtr + dictSize; - short offcodeNCount[MaxOff+1]; - unsigned offcodeMaxValue = MaxOff; - size_t dictID; - - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); - assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); - - dictPtr += 4; /* skip magic number */ - dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); - dictPtr += 4; + const BYTE* const dictEnd = dictPtr + dictSize - 8; { unsigned maxSymbolValue = 255; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); @@ -2808,7 +2783,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, } { unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted); /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ @@ -2856,6 +2831,43 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, bs->rep[1] = MEM_readLE32(dictPtr+4); bs->rep[2] = MEM_readLE32(dictPtr+8); dictPtr += 12; + DEBUGLOG(1, "size %u)", (unsigned)(dictPtr - (const BYTE*)dict)); + return dictPtr - (const BYTE*)dict; +} + +/* Dictionary format : + * See : + * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format + */ +/*! ZSTD_loadZstdDictionary() : + * @return : dictID, or an error code + * assumptions : magic number supposed already checked + * dictSize supposed > 8 + */ +static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, + ZSTD_matchState_t* ms, + ZSTD_cwksp* ws, + ZSTD_CCtx_params const* params, + const void* dict, size_t dictSize, + ZSTD_dictTableLoadMethod_e dtlm, + void* workspace) +{ + size_t dictID; + size_t eSize; + const BYTE* dictPtr = (const BYTE*)dict; + const BYTE* const dictEnd = dictPtr + dictSize; + short offcodeNCount[MaxOff+1]; + unsigned offcodeMaxValue = MaxOff; + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1< 8); + assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); + eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); + + dictPtr += 4; /* skip magic number */ + dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); + dictPtr += 4; + + dictPtr += eSize - 8; /* size of header + magic number already accounted for */ { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); U32 offcodeMax = MaxOff; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 14036f873f5..62ee3f9bc64 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -930,7 +930,17 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) #if defined (__cplusplus) } #endif - +/* =============================================================== + * Public declarations + * These prototypes may be called from sources not in lib/compress + * =============================================================== */ + +/* ZSTD_loadCEntropy() : + * dict : must point at beginning of a valid zstd dictionary. + * return : size of entropy tables read */ +size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, + short* offcodeNCount, unsigned* offcodeMaxValue, + const void* const dict, size_t dictSize); /* ============================================================== * Private declarations From 04fb42b4f35b256b61108dcf0167cf21d81fcfbe Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 11:32:08 -0500 Subject: [PATCH 059/402] Integrated refactor into getDictHeaderSize, now passes tests --- lib/compress/zstd_compress.c | 10 ++++++---- lib/dictBuilder/zdict.c | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 0ebbf1926ac..3c04718e3e4 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2772,8 +2772,8 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize) { - const BYTE* dictPtr = (const BYTE*)dict; - const BYTE* const dictEnd = dictPtr + dictSize - 8; + const BYTE* dictPtr = (const BYTE*)dict + 8; + const BYTE* const dictEnd = dictPtr + dictSize; { unsigned maxSymbolValue = 255; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); @@ -2852,15 +2852,17 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_dictTableLoadMethod_e dtlm, void* workspace) { - size_t dictID; - size_t eSize; const BYTE* dictPtr = (const BYTE*)dict; const BYTE* const dictEnd = dictPtr + dictSize; short offcodeNCount[MaxOff+1]; unsigned offcodeMaxValue = MaxOff; + size_t dictID; + size_t eSize; + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1< 8); assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); + eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); dictPtr += 4; /* skip magic number */ diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6db57b1448c..6d76fb5218a 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -48,7 +48,7 @@ # define ZDICT_STATIC_LINKING_ONLY #endif #include "zdict.h" -#include "decompress/zstd_decompress_internal.h" /* ZSTD_entropyDTables_t */ +#include "compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */ /*-************************************* @@ -105,14 +105,19 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0; { size_t headerSize; - ZSTD_entropyDTables_t* dummyEntropyTables = (ZSTD_entropyDTables_t*)malloc(sizeof(ZSTD_entropyDTables_t)); - if (!dummyEntropyTables) { + unsigned offcodeMaxValue = MaxOff; + ZSTD_compressedBlockState_t* dummyBs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); + U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); + short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); + if (!dummyBs || !wksp) { return 0; } - dummyEntropyTables->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); - headerSize = ZSTD_loadDEntropy(dummyEntropyTables, dictBuffer, dictSize); - free(dummyEntropyTables); - return ZSTD_isError(headerSize) ? 0 : headerSize; + + headerSize = ZSTD_loadCEntropy(dummyBs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); + free(dummyBs); + free(wksp); + free(offcodeNCount); + return headerSize; } } From c787b351ea37dc248a982a68ac5302b21f5cb962 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 11:46:25 -0500 Subject: [PATCH 060/402] Use ZSTD Error codes, improve explanation of ZSTD_loadCEntropy() and ZSTD_loadDEntropy() --- lib/compress/zstd_compress.c | 4 ++-- lib/compress/zstd_compress_internal.h | 4 ++-- lib/decompress/zstd_decompress_internal.h | 2 +- lib/dictBuilder/zdict.c | 8 ++++---- lib/dictBuilder/zdict.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 3c04718e3e4..edc238b8b13 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2772,7 +2772,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize) { - const BYTE* dictPtr = (const BYTE*)dict + 8; + const BYTE* dictPtr = (const BYTE*)dict + 8; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; { unsigned maxSymbolValue = 255; @@ -2869,7 +2869,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); dictPtr += 4; - dictPtr += eSize - 8; /* size of header + magic number already accounted for */ + dictPtr += eSize - 8; { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); U32 offcodeMax = MaxOff; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 62ee3f9bc64..0811ccf9a28 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -931,13 +931,13 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) } #endif /* =============================================================== - * Public declarations + * Shared internal declarations * These prototypes may be called from sources not in lib/compress * =============================================================== */ /* ZSTD_loadCEntropy() : * dict : must point at beginning of a valid zstd dictionary. - * return : size of entropy tables read */ + * return : size of dictionary header (size of magic number + dict ID + entropy tables) */ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index ccbdfa090fa..99eab854ce1 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -160,7 +160,7 @@ struct ZSTD_DCtx_s /*! ZSTD_loadDEntropy() : * dict : must point at beginning of a valid zstd dictionary. - * @return : size of entropy tables read */ + * @return : size of dictionary header (size of magic number + dict ID + entropy tables) */ size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, const void* const dict, size_t const dictSize); diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6d76fb5218a..1c0915fe37a 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -102,22 +102,22 @@ unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize) size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { - if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0; + if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted); { size_t headerSize; unsigned offcodeMaxValue = MaxOff; ZSTD_compressedBlockState_t* dummyBs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); - if (!dummyBs || !wksp) { - return 0; + if (!dummyBs || !wksp || !offcodeNCount) { + return ERROR(memory_allocation); } headerSize = ZSTD_loadCEntropy(dummyBs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); free(dummyBs); free(wksp); free(offcodeNCount); - return headerSize; + return headerSize; /* this may be an error value if ZSTD_loadCEntropy() encountered an error */ } } diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index bb89f1f9f9d..1313bd21448 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -64,7 +64,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap /*====== Helper functions ======*/ ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ -ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns zero if error (not a valid dictionary or mem alloc failure) */ +ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns a ZSTD error code on failure */ ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); From 4a61aaf368022e9fda91e9eb277dec8307b4e162 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 11:47:47 -0500 Subject: [PATCH 061/402] Remove redundant comment --- lib/dictBuilder/zdict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 1c0915fe37a..6d2bfd54462 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -117,7 +117,7 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) free(dummyBs); free(wksp); free(offcodeNCount); - return headerSize; /* this may be an error value if ZSTD_loadCEntropy() encountered an error */ + return headerSize; } } From 6ce335371bf4249bc827efbf070ef1f51ee78b1a Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 13:58:35 -0500 Subject: [PATCH 062/402] Add error forwarding to loadCEntropy(), make check for dictSize >= 8 from bad merge --- lib/compress/zstd_compress.c | 19 ++++++++----------- lib/compress/zstd_compress_internal.h | 5 ++++- lib/dictBuilder/zdict.c | 15 +++++++++++---- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index edc238b8b13..b99f91fed7c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2775,6 +2775,10 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, const BYTE* dictPtr = (const BYTE*)dict + 8; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); + assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); + { unsigned maxSymbolValue = 255; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted); @@ -2831,7 +2835,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, bs->rep[1] = MEM_readLE32(dictPtr+4); bs->rep[2] = MEM_readLE32(dictPtr+8); dictPtr += 12; - DEBUGLOG(1, "size %u)", (unsigned)(dictPtr - (const BYTE*)dict)); + return dictPtr - (const BYTE*)dict; } @@ -2859,17 +2863,10 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, size_t dictID; size_t eSize; - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1< 8); - assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); - + dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); - - dictPtr += 4; /* skip magic number */ - dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr); - dictPtr += 4; - - dictPtr += eSize - 8; + FORWARD_IF_ERROR(eSize); + dictPtr += eSize; { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); U32 offcodeMax = MaxOff; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 0811ccf9a28..48bfea64aed 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -930,6 +930,7 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) #if defined (__cplusplus) } #endif + /* =============================================================== * Shared internal declarations * These prototypes may be called from sources not in lib/compress @@ -937,7 +938,9 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) /* ZSTD_loadCEntropy() : * dict : must point at beginning of a valid zstd dictionary. - * return : size of dictionary header (size of magic number + dict ID + entropy tables) */ + * return : size of dictionary header (size of magic number + dict ID + entropy tables) + * assumptions : magic number supposed already checked + * and dictSize >= 8 */ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6d2bfd54462..499a309c598 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -106,15 +106,22 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { size_t headerSize; unsigned offcodeMaxValue = MaxOff; - ZSTD_compressedBlockState_t* dummyBs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); + ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); - if (!dummyBs || !wksp || !offcodeNCount) { + if (!bs || !wksp || !offcodeNCount) { return ERROR(memory_allocation); } - headerSize = ZSTD_loadCEntropy(dummyBs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); - free(dummyBs); + int i; + for (i = 0; i < ZSTD_REP_NUM; ++i) + bs->rep[i] = repStartValue[i]; + bs->entropy.huf.repeatMode = HUF_repeat_none; + bs->entropy.fse.offcode_repeatMode = FSE_repeat_none; + bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none; + bs->entropy.fse.litlength_repeatMode = FSE_repeat_none; + headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); + free(bs); free(wksp); free(offcodeNCount); return headerSize; From b39149e15674ddfe0956850a6394ef48ace94af8 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 14:07:21 -0500 Subject: [PATCH 063/402] Expose ZSTD_reset_compressedBlockState() to shared API --- lib/compress/zstd_compress.c | 6 +++--- lib/compress/zstd_compress_internal.h | 2 ++ lib/dictBuilder/zdict.c | 10 ++-------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b99f91fed7c..ccd7af3dfdd 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1248,7 +1248,7 @@ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1, assert(cParams1.strategy == cParams2.strategy); } -static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) +void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) { int i; for (i = 0; i < ZSTD_REP_NUM; ++i) @@ -2835,7 +2835,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, bs->rep[1] = MEM_readLE32(dictPtr+4); bs->rep[2] = MEM_readLE32(dictPtr+8); dictPtr += 12; - + return dictPtr - (const BYTE*)dict; } @@ -2846,7 +2846,7 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, /*! ZSTD_loadZstdDictionary() : * @return : dictID, or an error code * assumptions : magic number supposed already checked - * dictSize supposed > 8 + * dictSize supposed >= 8 */ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 48bfea64aed..28c46e89544 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -945,6 +945,8 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); +void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); + /* ============================================================== * Private declarations * These prototypes shall only be called from within lib/compress diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 499a309c598..fc01c90f31f 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -112,14 +112,8 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) if (!bs || !wksp || !offcodeNCount) { return ERROR(memory_allocation); } - - int i; - for (i = 0; i < ZSTD_REP_NUM; ++i) - bs->rep[i] = repStartValue[i]; - bs->entropy.huf.repeatMode = HUF_repeat_none; - bs->entropy.fse.offcode_repeatMode = FSE_repeat_none; - bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none; - bs->entropy.fse.litlength_repeatMode = FSE_repeat_none; + + ZSTD_reset_compressedBlockState(bs); headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); free(bs); free(wksp); From d06b90692b7826db8b6f7258fb4bef77a1fbb442 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 14:08:55 -0500 Subject: [PATCH 064/402] Move asserts to loadZstdDictionary() --- lib/compress/zstd_compress.c | 8 ++++---- lib/dictBuilder/zdict.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ccd7af3dfdd..247470e5d3f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2775,10 +2775,6 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, const BYTE* dictPtr = (const BYTE*)dict + 8; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); - assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); - { unsigned maxSymbolValue = 255; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted); @@ -2863,6 +2859,10 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, size_t dictID; size_t eSize; + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); + assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); + dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); FORWARD_IF_ERROR(eSize); diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index fc01c90f31f..de8576af3f1 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -112,7 +112,7 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) if (!bs || !wksp || !offcodeNCount) { return ERROR(memory_allocation); } - + ZSTD_reset_compressedBlockState(bs); headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); free(bs); From d9c475f3b3e7e22d8f78d2b9c501ccf875d8d81f Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 7 Nov 2019 16:24:55 -0500 Subject: [PATCH 065/402] Fix static analyze error, use proper bounds for dictEnd --- lib/compress/zstd_compress.c | 3 ++- lib/dictBuilder/zdict.c | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 247470e5d3f..89c34d5e1c9 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2772,8 +2772,9 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize) { - const BYTE* dictPtr = (const BYTE*)dict + 8; /* skip magic num and dict ID */ + const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; + dictPtr += 8; { unsigned maxSymbolValue = 255; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index de8576af3f1..9cee71beba3 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -107,14 +107,15 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { size_t headerSize; unsigned offcodeMaxValue = MaxOff; ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); + if (!bs) return ERROR(memory_allocation); U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); + if (!wksp) return ERROR(memory_allocation); short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); - if (!bs || !wksp || !offcodeNCount) { - return ERROR(memory_allocation); - } + if (!offcodeNCount) return ERROR(memory_allocation); ZSTD_reset_compressedBlockState(bs); headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); + free(bs); free(wksp); free(offcodeNCount); From c85d10d0ea5b4aebcf5cb4f2abb253f6de860658 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Fri, 8 Nov 2019 11:20:57 -0500 Subject: [PATCH 066/402] Remove mixed declarations --- lib/dictBuilder/zdict.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 9cee71beba3..344ab446b9d 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -102,25 +102,26 @@ unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize) size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) { + size_t headerSize; if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted); - { size_t headerSize; - unsigned offcodeMaxValue = MaxOff; + { unsigned offcodeMaxValue = MaxOff; ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); - if (!bs) return ERROR(memory_allocation); U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); - if (!wksp) return ERROR(memory_allocation); short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short)); - if (!offcodeNCount) return ERROR(memory_allocation); + if (!bs || !wksp || !offcodeNCount) { + headerSize = ERROR(memory_allocation); + } else { + ZSTD_reset_compressedBlockState(bs); + headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); + } - ZSTD_reset_compressedBlockState(bs); - headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize); - free(bs); free(wksp); free(offcodeNCount); - return headerSize; } + + return headerSize; } /*-******************************************************** From 106278e7e5fafaea3b7deb4147bdc8071562d2f0 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Nov 2019 18:59:06 -0500 Subject: [PATCH 067/402] Use lowercase windows.h Helps for cross builds, doesn't matter on Windows itself. --- programs/timefn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/timefn.h b/programs/timefn.h index d1ddd31b1c0..37802a80466 100644 --- a/programs/timefn.h +++ b/programs/timefn.h @@ -47,7 +47,7 @@ extern "C" { ******************************************/ #if defined(_WIN32) /* Windows */ - #include /* LARGE_INTEGER */ + #include /* LARGE_INTEGER */ typedef LARGE_INTEGER UTIL_time_t; #define UTIL_TIME_INITIALIZER { { 0, 0 } } From 098b36e9ab6ae29f1a2f0e67911f0e27442a03e7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 13 Nov 2019 09:50:15 -0800 Subject: [PATCH 068/402] clarifications for Block_Maximum_Size as a follow up of #1882 --- doc/zstd_compression_format.md | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/doc/zstd_compression_format.md b/doc/zstd_compression_format.md index 90ac0fe9bcd..fc61726fc98 100644 --- a/doc/zstd_compression_format.md +++ b/doc/zstd_compression_format.md @@ -16,7 +16,7 @@ Distribution of this document is unlimited. ### Version -0.3.4 (16/08/19) +0.3.5 (13/11/19) Introduction @@ -341,6 +341,8 @@ The structure of a block is as follows: |:--------------:|:---------------:| | 3 bytes | n bytes | +__`Block_Header`__ + `Block_Header` uses 3 bytes, written using __little-endian__ convention. It contains 3 fields : @@ -385,17 +387,30 @@ There are 4 block types : __`Block_Size`__ The upper 21 bits of `Block_Header` represent the `Block_Size`. + When `Block_Type` is `Compressed_Block` or `Raw_Block`, -`Block_Size` is the size of `Block_Content`, hence excluding `Block_Header`. -When `Block_Type` is `RLE_Block`, `Block_Content`’s size is always 1, -and `Block_Size` represents the number of times this byte must be repeated. -A block can contain and decompress into any number of bytes (even zero), -up to `Block_Maximum_Decompressed_Size`, which is the smallest of: -- Window_Size +`Block_Size` is the size of `Block_Content` (hence excluding `Block_Header`). + +When `Block_Type` is `RLE_Block`, since `Block_Content`’s size is always 1, +`Block_Size` represents the number of times this byte must be repeated. + +`Block_Size` is limited by `Block_Maximum_Size` (see below). + +__`Block_Content`__ and __`Block_Maximum_Size`__ + +The size of `Block_Content` is limited by `Block_Maximum_Size`, +which is the smallest of: +- `Window_Size` - 128 KB -If this condition cannot be respected when generating a `Compressed_Block`, -the block must be sent uncompressed instead (`Raw_Block`). +`Block_Maximum_Size` is constant for a given frame. +This maximum is applicable to both the decompressed size +and the compressed size of any block in the frame. + +The reasoning for this limit is that a decoder can read this information +at the beginning of a frame and use it to allocate buffers. +The guarantees on the size of blocks ensure that +the buffers will be large enough for any following block of the valid frame. Compressed Blocks @@ -1658,6 +1673,7 @@ or at least provide a meaningful error code explaining for which reason it canno Version changes --------------- +- 0.3.5 : clarifications for Block_Maximum_Size - 0.3.4 : clarifications for FSE decoding table - 0.3.3 : clarifications for field Block_Size - 0.3.2 : remove additional block size restriction on compressed blocks From c26d32c91cdf70d1400b581b7418dda409bfe44c Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 14 Nov 2019 13:12:17 -0500 Subject: [PATCH 069/402] Change superblock #include to be last --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_superblock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b8349d8bab4..954d8254e8e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -20,7 +20,6 @@ #include "fse.h" #define HUF_STATIC_LINKING_ONLY #include "huf.h" -#include "zstd_compress_superblock.h" #include "zstd_compress_internal.h" #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" @@ -29,6 +28,7 @@ #include "zstd_lazy.h" #include "zstd_opt.h" #include "zstd_ldm.h" +#include "zstd_compress_superblock.h" /*-************************************* diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 3dfb16dee3b..eb3e369d636 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -13,9 +13,9 @@ ***************************************/ #include "hist.h" /* HIST_countFast_wksp */ #include "zstd_compress_internal.h" -#include "zstd_compress_superblock.h" #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" +#include "zstd_compress_superblock.h" /*-************************************* * Superblock entropy buffer structs From 982830b081d53a8fdffeef61def75fd7150a6e12 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 14 Nov 2019 10:48:55 -0800 Subject: [PATCH 070/402] Fixing hashLog error 2^26=64Mib --- programs/zstd.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index e3daa4c87ac..5ea7fd8943e 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -402,7 +402,7 @@ The list of available _options_: Bigger hash tables cause less collisions which usually makes compression faster, but requires more memory during compression. - The minimum _hlog_ is 6 (64 B) and the maximum is 26 (128 MiB). + The minimum _hlog_ is 6 (64 B) and the maximum is 26 (64 MiB). - `chainLog`=_clog_, `clog`=_clog_: Specify the maximum number of bits for a hash chain or a binary tree. From 0ede342acc2c26f87ae962fa88e158904d4198c4 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Nov 2019 15:13:35 -0500 Subject: [PATCH 071/402] Fix MinGW cross build from Unix generate_res.bat seems rather pointless, am I missing something? I just inlined it into the Makefile. --- programs/Makefile | 26 +++++++++++++++++--------- programs/windres/generate_res.bat | 11 ----------- 2 files changed, 17 insertions(+), 20 deletions(-) delete mode 100644 programs/windres/generate_res.bat diff --git a/programs/Makefile b/programs/Makefile index 64dcae0028e..5ed61f97fec 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -165,15 +165,15 @@ $(ZSTDDECOMP_O): CFLAGS += $(ALIGN_LOOP) zstd : CPPFLAGS += $(THREAD_CPP) $(ZLIBCPP) $(LZMACPP) $(LZ4CPP) zstd : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD) zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) +ifneq (,$(filter Windows%,$(OS))) +zstd : $(RES_FILE) +endif zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o @echo "$(THREAD_MSG)" @echo "$(ZLIB_MSG)" @echo "$(LZMA_MSG)" @echo "$(LZ4_MSG)" -ifneq (,$(filter Windows%,$(OS))) - windres/generate_res.bat -endif - $(CC) $(FLAGS) $^ $(RES_FILE) -o $@$(EXT) $(LDFLAGS) + $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) .PHONY: zstd-release zstd-release: DEBUGFLAGS := -DBACKTRACE_ENABLE=0 @@ -183,11 +183,11 @@ zstd-release: zstd zstd32 : CPPFLAGS += $(THREAD_CPP) zstd32 : LDFLAGS += $(THREAD_LD) zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) -zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c ifneq (,$(filter Windows%,$(OS))) - windres/generate_res.bat +zstd32 : $(RES32_FILE) endif - $(CC) -m32 $(FLAGS) $^ $(RES32_FILE) -o $@$(EXT) +zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c + $(CC) -m32 $(FLAGS) $^ -o $@$(EXT) zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) @@ -235,8 +235,16 @@ zstdmt: zstd ln -sf zstd zstdmt .PHONY: generate_res -generate_res: - windres/generate_res.bat +generate_res: $(RES64_FILE) $(RES32_FILE) + +ifneq (,$(filter Windows%,$(OS))) +RC ?= windres +# http://stackoverflow.com/questions/708238/how-do-i-add-an-icon-to-a-mingw-gcc-compiled-executable +$(RES64_FILE): windres/zstd.rc + $(RC) -o $@ -I ../lib -I windres -i $< -O coff -F pe-x86-64 +$(RES32_FILE): windres/zstd.rc + $(RC) -o $@ -I ../lib -I windres -i $< -O coff -F pe-i386 +endif .PHONY: clean clean: diff --git a/programs/windres/generate_res.bat b/programs/windres/generate_res.bat deleted file mode 100644 index 7ff9aef5102..00000000000 --- a/programs/windres/generate_res.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -REM http://stackoverflow.com/questions/708238/how-do-i-add-an-icon-to-a-mingw-gcc-compiled-executable - -where /q windres.exe -IF ERRORLEVEL 1 ( - ECHO The windres.exe is missing. Ensure it is installed and placed in your PATH. - EXIT /B -) ELSE ( - windres.exe -I ../lib -I windres -i windres/zstd.rc -O coff -F pe-x86-64 -o windres/zstd64.res - windres.exe -I ../lib -I windres -i windres/zstd.rc -O coff -F pe-i386 -o windres/zstd32.res -) From 10552eaffef84c011f67af0e04f0780b50a5ab26 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Nov 2019 15:34:00 -0500 Subject: [PATCH 072/402] Fix MinGW cross install from Unix Needed a bunch of `$(EXT)` --- programs/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index 5ed61f97fec..668e6135cea 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -350,10 +350,10 @@ INSTALL_MAN ?= $(INSTALL_DATA) install: zstd @echo Installing binaries @$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MAN1DIR)/ - @$(INSTALL_PROGRAM) zstd $(DESTDIR)$(BINDIR)/zstd - @ln -sf zstd $(DESTDIR)$(BINDIR)/zstdcat - @ln -sf zstd $(DESTDIR)$(BINDIR)/unzstd - @ln -sf zstd $(DESTDIR)$(BINDIR)/zstdmt + @$(INSTALL_PROGRAM) zstd$(EXT) $(DESTDIR)$(BINDIR)/zstd$(EXT) + @ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdcat$(EXT) + @ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/unzstd$(EXT) + @ln -sf zstd$(EXT) $(DESTDIR)$(BINDIR)/zstdmt$(EXT) @$(INSTALL_SCRIPT) zstdless $(DESTDIR)$(BINDIR)/zstdless @$(INSTALL_SCRIPT) zstdgrep $(DESTDIR)$(BINDIR)/zstdgrep @echo Installing man pages From d9646dcbb5d6fd265bfe19b5376ef8e15cf3cf11 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Thu, 14 Nov 2019 19:39:09 -0500 Subject: [PATCH 073/402] Fixed main compression logic changes --- lib/compress/zstd_compress.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 954d8254e8e..5bb042483ae 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2572,23 +2572,25 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; - { int useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); - size_t cSize = 0; + { size_t cSize; + int useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); if (useTargetCBlockSize) { cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cSize); } else { cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, - ip, blockSize, 0 /* frame */); + ip, blockSize, 1 /* frame */); FORWARD_IF_ERROR(cSize); if (cSize == 0) { /* block is not compressible */ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cSize); } else { - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24(op, cBlockHeader24); + U32 const cBlockHeader = cSize == 1 ? + lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : + lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(op, cBlockHeader); cSize += ZSTD_blockHeaderSize; } } From b3c9fc27b4596beb7452ae71647a97eb7fad08cd Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Tue, 5 Nov 2019 14:14:02 +0100 Subject: [PATCH 074/402] Optimized loop bounds to allow the compiler to unroll the loop. This has no measurable impact on large files but improves small file decompression by ~1-2% for 10kB, benchmarked with: head -c 10000 silesia.tar > /tmp/test make CC=/usr/local/bin/clang-9 BUILD_STATIC=1 && ./lzbench -ezstd -t1,5 /tmp/test --- lib/decompress/huf_decompress.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index bb2d0a96bc1..fd417088c5c 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -181,17 +181,29 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize /* fill DTable */ { U32 n; - for (n=0; n> 1; - U32 u; + size_t const nEnd = nbSymbols; + for (n=0; n> 1; + size_t const uStart = rankVal[w]; + size_t const uEnd = uStart + length; + size_t u; HUF_DEltX1 D; - D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); - for (u = rankVal[w]; u < rankVal[w] + length; u++) - dt[u] = D; - rankVal[w] += length; - } } - + D.byte = (BYTE)n; + D.nbBits = (BYTE)(tableLog + 1 - w); + rankVal[w] = uEnd; + if (length < 4) { + /* Use length in the loop bound so the compiler knows it is short. */ + for (u = 0; u < length; ++u) + dt[uStart + u] = D; + } else { + /* Unroll the loop 4 times, we know it is a power of 2. */ + for (u = uStart; u < uEnd; u += 4) { + dt[u + 0] = D; + dt[u + 1] = D; + dt[u + 2] = D; + dt[u + 3] = D; + } } } } return iSize; } From 75c34684c0e8fedf3b6afffe91f2ad5321835860 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Fri, 15 Nov 2019 12:26:48 -0500 Subject: [PATCH 075/402] Modified existing RLE test to take compressed size into account --- tests/fuzzer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 88f3b83f834..e757daaba89 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1999,14 +1999,14 @@ static int basicUnitTests(U32 const seed, double compressibility) /* long rle test */ { size_t sampleSize = 0; + size_t expectedCompressedSize = 39; /* two RLE blocks, zstd 1.4.4 */ DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); - RDG_genBuffer(CNBuffer, sampleSize, compressibility, 0., seed+1); memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); sampleSize += 256 KB - 1; - RDG_genBuffer((char*)CNBuffer+sampleSize, 96 KB, compressibility, 0., seed+2); + memset((char*)CNBuffer+sampleSize, 'A', 96 KB); sampleSize += 96 KB; cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1); - if (ZSTD_isError(cSize)) goto _output_error; + if (ZSTD_isError(cSize) || cSize > expectedCompressedSize * 1.1) goto _output_error; { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize)); if (regenSize!=sampleSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); From 6b5c10b48c0faa2034c14c93a233dc3a241aa373 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Fri, 15 Nov 2019 19:46:06 +0100 Subject: [PATCH 076/402] shared library: rename import library with .dll.a extension mort of open source project are using this extension for the import library. The Win32 linker is supporting this extension, see https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_ld_the_GNU_Linker/win32.html section "direct linking to a dll" --- lib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Makefile b/lib/Makefile index 273ceb90490..fd1710cf1a0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -161,7 +161,7 @@ ifneq (,$(filter Windows%,$(OS))) LIBZSTD = dll\libzstd.dll $(LIBZSTD): $(ZSTD_FILES) @echo compiling dynamic library $(LIBVER) - $(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll\libzstd.lib -shared $^ -o $@ + $(CC) $(FLAGS) -DZSTD_DLL_EXPORT=1 -Wl,--out-implib,dll\libzstd.dll.a -shared $^ -o $@ else From db8efbfe7d5ce6df3e09ef2be93eb4234b32f511 Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Fri, 15 Nov 2019 14:57:44 -0500 Subject: [PATCH 077/402] Updated comment to reflect actual compression behavior --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index e757daaba89..7bf84196dfe 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1999,7 +1999,7 @@ static int basicUnitTests(U32 const seed, double compressibility) /* long rle test */ { size_t sampleSize = 0; - size_t expectedCompressedSize = 39; /* two RLE blocks, zstd 1.4.4 */ + size_t expectedCompressedSize = 39; /* block 1: RLE, block 2: compressed, block 3: RLE, zstd 1.4.4 */ DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); sampleSize += 256 KB - 1; From dba767c0bba79f7ba7caac937799f4a6e5d36dc3 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 15 Nov 2019 18:44:51 -0800 Subject: [PATCH 078/402] Leaving room for checksum --- lib/compress/zstd_compress.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d4e7590bece..4ff825d9583 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2480,8 +2480,11 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * enough for SuperBlock compression. * In such case, fall back to normal compression. This is possible because * targetCBlockSize is best effort not a guarantee. */ - if (cSize != ERROR(dstSize_tooSmall)) return cSize; - else { + if (cSize == ERROR(dstSize_tooSmall) || (dstCapacity - cSize) < 4) { + /* We check (dstCapacity - cSize) < 4 above because we have to make sure + * to leave enouch room for the checksum that will eventually get added in + * the epilogue. Otherwise, we're just going to throw the dstSize_tooSmall + * error there instead of here */ BYTE* const ostart = (BYTE*)dst; /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, * compress normally. @@ -2498,7 +2501,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, MEM_writeLE24(ostart, cBlockHeader24); cSize += ZSTD_blockHeaderSize; } - } + } else return cSize; } if (!ZSTD_isError(cSize) && cSize != 0) { @@ -2853,7 +2856,7 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, short* offcodeNCount, unsigned* offcodeMaxValue, - const void* const dict, size_t dictSize) + const void* const dict, size_t dictSize) { const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; From 2d5d961a60b72c5a7cffaf25d0d16b599f45343d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 15 Nov 2019 19:00:53 -0800 Subject: [PATCH 079/402] Typo in comment --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 4ff825d9583..0639d327240 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2482,7 +2482,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * targetCBlockSize is best effort not a guarantee. */ if (cSize == ERROR(dstSize_tooSmall) || (dstCapacity - cSize) < 4) { /* We check (dstCapacity - cSize) < 4 above because we have to make sure - * to leave enouch room for the checksum that will eventually get added in + * to leave enough room for the checksum that will eventually get added in * the epilogue. Otherwise, we're just going to throw the dstSize_tooSmall * error there instead of here */ BYTE* const ostart = (BYTE*)dst; From dade64428f093b111195cc1ac2e474633735a0cd Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 18 Nov 2019 08:43:14 -0800 Subject: [PATCH 080/402] Output regular uncompressed block when compressSequences fails --- lib/compress/zstd_compress.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 0639d327240..a883d21c18a 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2496,7 +2496,13 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, zc->bmi2); - if (!ZSTD_isError(cSize) && cSize != 0) { + + if (cSize == 0) { + /* If compressSequences didn't work, we just output a regular + * uncompressed block */ + cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize); + } else { U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); MEM_writeLE24(ostart, cBlockHeader24); cSize += ZSTD_blockHeaderSize; From bc3e21578de1788acd0b05f50a5d6bd674a0482c Mon Sep 17 00:00:00 2001 From: Sen Huang Date: Mon, 18 Nov 2019 16:39:16 -0500 Subject: [PATCH 081/402] No margin on RLE test size check --- tests/fuzzer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 7bf84196dfe..e14a4798bfb 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1999,14 +1999,14 @@ static int basicUnitTests(U32 const seed, double compressibility) /* long rle test */ { size_t sampleSize = 0; - size_t expectedCompressedSize = 39; /* block 1: RLE, block 2: compressed, block 3: RLE, zstd 1.4.4 */ + size_t expectedCompressedSize = 39; /* block 1, 2: compressed, block 3: RLE, zstd 1.4.4 */ DISPLAYLEVEL(3, "test%3i : Long RLE test : ", testNb++); memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1); sampleSize += 256 KB - 1; memset((char*)CNBuffer+sampleSize, 'A', 96 KB); sampleSize += 96 KB; cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize, 1); - if (ZSTD_isError(cSize) || cSize > expectedCompressedSize * 1.1) goto _output_error; + if (ZSTD_isError(cSize) || cSize > expectedCompressedSize) goto _output_error; { CHECK_NEWV(regenSize, ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize)); if (regenSize!=sampleSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); From 80586f5e8003fe235f1ef5bccaee88966baaaddf Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 18 Nov 2019 13:53:55 -0800 Subject: [PATCH 082/402] Reversing condition order and forwarding error --- lib/compress/zstd_compress.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a883d21c18a..6330b882163 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2480,11 +2480,13 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * enough for SuperBlock compression. * In such case, fall back to normal compression. This is possible because * targetCBlockSize is best effort not a guarantee. */ - if (cSize == ERROR(dstSize_tooSmall) || (dstCapacity - cSize) < 4) { - /* We check (dstCapacity - cSize) < 4 above because we have to make sure + if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) + /* We check (dstCapacity - cSize) >= 4 above because we have to make sure * to leave enough room for the checksum that will eventually get added in * the epilogue. Otherwise, we're just going to throw the dstSize_tooSmall * error there instead of here */ + return cSize; + else { BYTE* const ostart = (BYTE*)dst; /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, * compress normally. @@ -2497,6 +2499,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, zc->bmi2); + FORWARD_IF_ERROR(cSize); if (cSize == 0) { /* If compressSequences didn't work, we just output a regular * uncompressed block */ @@ -2507,7 +2510,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, MEM_writeLE24(ostart, cBlockHeader24); cSize += ZSTD_blockHeaderSize; } - } else return cSize; + } } if (!ZSTD_isError(cSize) && cSize != 0) { From b5fb2e7c12665c3c43676986dc5fab1613966f09 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 19 Nov 2019 01:21:53 -0500 Subject: [PATCH 083/402] Add Tool to Diagnose Whether Corrupt Blobs are Plausibly Bit-Flips I spend an increasing amount of my time looking at "Corrupted block detected" failures in decompression. Not infrequently, I suspect that it is the result of hardware failure, and that the blob has become bit-flipped or otherwise corrupted somewhere along the line. For that reason I was motivated to write a little tool to inspect blobs that fail to decompress, to try modifying them, and then check whether they decompress successfully. This seems like potentially a generally useful tool, so I figured it might be worth putting in `contrib/`. --- contrib/diagnose_corruption/.gitignore | 1 + contrib/diagnose_corruption/Makefile | 35 +++ .../diagnose_corruption/check_flipped_bits.c | 217 ++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 contrib/diagnose_corruption/.gitignore create mode 100644 contrib/diagnose_corruption/Makefile create mode 100644 contrib/diagnose_corruption/check_flipped_bits.c diff --git a/contrib/diagnose_corruption/.gitignore b/contrib/diagnose_corruption/.gitignore new file mode 100644 index 00000000000..a8e92b69b81 --- /dev/null +++ b/contrib/diagnose_corruption/.gitignore @@ -0,0 +1 @@ +check_flipped_bits diff --git a/contrib/diagnose_corruption/Makefile b/contrib/diagnose_corruption/Makefile new file mode 100644 index 00000000000..dc6fd29063d --- /dev/null +++ b/contrib/diagnose_corruption/Makefile @@ -0,0 +1,35 @@ +# ################################################################ +# Copyright (c) 2019-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under both the BSD-style license (found in the +# LICENSE file in the root directory of this source tree) and the GPLv2 (found +# in the COPYING file in the root directory of this source tree). +# ################################################################ + +.PHONY: all +all: check_flipped_bits + +ZSTDLIBDIR ?= ../../lib + +CFLAGS ?= -O3 +CFLAGS += -I$(ZSTDLIBDIR) -I$(ZSTDLIBDIR)/common -I$(ZSTDLIBDIR)/compress \ + -I$(ZSTDLIBDIR)/decompress +CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ + -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ + -Wstrict-prototypes -Wundef \ + -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ + -Wredundant-decls -Wmissing-prototypes +CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) +FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) + +.PHONY: $(ZSTDLIBDIR)/libzstd.a +$(ZSTDLIBDIR)/libzstd.a: + $(MAKE) -C $(ZSTDLIBDIR) libzstd.a + +check_flipped_bits: check_flipped_bits.c $(ZSTDLIBDIR)/libzstd.a + $(CC) $(FLAGS) $< -o $@$(EXT) $(ZSTDLIBDIR)/libzstd.a + +.PHONY: clean +clean: + rm -f check_flipped_bits \ No newline at end of file diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c new file mode 100644 index 00000000000..8555959e418 --- /dev/null +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2019-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "zstd.h" + +#include +#include +#include +#include +#include +#include + +typedef struct { + char *input; + size_t input_size; + + char *perturbed; /* same size as input */ + + char *output; + size_t output_size; + + ZSTD_DCtx* dctx; +} stuff_t; + +static void free_stuff(stuff_t* stuff) { + free(stuff->input); + free(stuff->output); + ZSTD_freeDCtx(stuff->dctx); +} + +static void usage(void) { + fprintf(stderr, "check_flipped_bits input_filename"); + exit(1); +} + +static char* readFile(const char* filename, size_t* size) { + struct stat statbuf; + int ret; + FILE* f; + char *buf; + size_t bytes_read; + + ret = stat(filename, &statbuf); + if (ret != 0) { + fprintf(stderr, "stat failed: %m\n"); + return NULL; + } + if ((statbuf.st_mode & S_IFREG) != S_IFREG) { + fprintf(stderr, "Input must be regular file\n"); + return NULL; + } + + *size = statbuf.st_size; + + f = fopen(filename, "r"); + if (f == NULL) { + fprintf(stderr, "fopen failed: %m\n"); + return NULL; + } + + buf = malloc(*size); + if (buf == NULL) { + fprintf(stderr, "malloc failed\n"); + } + + bytes_read = fread(buf, 1, *size, f); + if (bytes_read != *size) { + fprintf(stderr, "failed to read whole file\n"); + free(buf); + return NULL; + } + + ret = fclose(f); + if (ret != 0) { + fprintf(stderr, "fclose failed: %m\n"); + free(buf); + return NULL; + } + + return buf; +} + +static int init_stuff(stuff_t* stuff, int argc, char *argv[]) { + const char* input_filename; + + if (argc != 2) { + usage(); + } + + input_filename = argv[1]; + stuff->input_size = 0; + stuff->input = readFile(input_filename, &stuff->input_size); + if (stuff->input == NULL) { + fprintf(stderr, "Failed to read input file.\n"); + return 0; + } + + stuff->perturbed = malloc(stuff->input_size); + if (stuff->perturbed == NULL) { + fprintf(stderr, "malloc failed.\n"); + return 0; + } + memcpy(stuff->perturbed, stuff->input, stuff->input_size); + + stuff->output_size = ZSTD_DStreamOutSize(); + stuff->output = malloc(stuff->output_size); + if (stuff->output == NULL) { + fprintf(stderr, "malloc failed.\n"); + return 0; + } + + stuff->dctx = ZSTD_createDCtx(); + if (stuff->dctx == NULL) { + return 0; + } + + return 1; +} + +static int test_decompress(stuff_t* stuff) { + size_t ret; + ZSTD_inBuffer in = {stuff->perturbed, stuff->input_size, 0}; + ZSTD_outBuffer out = {stuff->output, stuff->output_size, 0}; + ZSTD_DCtx* dctx = stuff->dctx; + + ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); + ZSTD_DCtx_refDDict(dctx, NULL); + + while (in.pos != in.size) { + out.pos = 0; + ret = ZSTD_decompressStream(dctx, &out, &in); + + if (ZSTD_isError(ret)) { + /* + fprintf( + stderr, "Decompression failed: %s\n", ZSTD_getErrorName(ret)); + */ + return 0; + } + } + + return 1; +} + +static int perturb_bits(stuff_t* stuff) { + size_t pos; + size_t bit; + for (pos = 0; pos < stuff->input_size; pos++) { + unsigned char old_val = stuff->input[pos]; + if (pos % 1000 == 0) { + fprintf(stderr, "Perturbing byte %zu\n", pos); + } + for (bit = 0; bit < 8; bit++) { + unsigned char new_val = old_val ^ (1 << bit); + stuff->perturbed[pos] = new_val; + if (test_decompress(stuff)) { + fprintf( + stderr, + "Flipping byte %zu bit %zu (0x%02x -> 0x%02x) " + "produced a successful decompression!\n", + pos, bit, old_val, new_val); + } + } + stuff->perturbed[pos] = old_val; + } + return 1; +} + +static int perturb_bytes(stuff_t* stuff) { + size_t pos; + size_t new_val; + for (pos = 0; pos < stuff->input_size; pos++) { + unsigned char old_val = stuff->input[pos]; + if (pos % 1000 == 0) { + fprintf(stderr, "Perturbing byte %zu\n", pos); + } + for (new_val = 0; new_val < 256; new_val++) { + stuff->perturbed[pos] = new_val; + if (test_decompress(stuff)) { + fprintf( + stderr, + "Changing byte %zu (0x%02x -> 0x%02x) " + "produced a successful decompression!\n", + pos, old_val, (unsigned char)new_val); + } + } + stuff->perturbed[pos] = old_val; + } + return 1; +} + +int main(int argc, char* argv[]) { + stuff_t stuff; + + if(!init_stuff(&stuff, argc, argv)) { + fprintf(stderr, "Failed to init.\n"); + return 1; + } + + if (test_decompress(&stuff)) { + fprintf(stderr, "Blob already decompresses successfully!\n"); + return 1; + } + + perturb_bits(&stuff); + + perturb_bytes(&stuff); + + free_stuff(&stuff); +} \ No newline at end of file From 722149cf2b8d28e88729b524bdc6a2ca7b51dea5 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 19 Nov 2019 01:57:15 -0500 Subject: [PATCH 084/402] Easy: Update Comment on `ZSTD_initDStream()` --- lib/zstd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstd.h b/lib/zstd.h index 72080ea87e8..f6f310150ce 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -763,7 +763,7 @@ ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* This function is redundant with the advanced API and equivalent to: * - * ZSTD_DCtx_reset(zds); + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); * ZSTD_DCtx_refDDict(zds, NULL); */ ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); From b032a6e1d917489c64726bae72198b276691d0ad Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 19 Nov 2019 09:55:13 -0800 Subject: [PATCH 085/402] Updated some more outdated bounds --- programs/zstd.1.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 5ea7fd8943e..3295b849a1e 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -402,7 +402,7 @@ The list of available _options_: Bigger hash tables cause less collisions which usually makes compression faster, but requires more memory during compression. - The minimum _hlog_ is 6 (64 B) and the maximum is 26 (64 MiB). + The minimum _hlog_ is 6 (64 B) and the maximum is 30 (1 GiB). - `chainLog`=_clog_, `clog`=_clog_: Specify the maximum number of bits for a hash chain or a binary tree. @@ -413,7 +413,8 @@ The list of available _options_: compression. This option is ignored for the ZSTD_fast strategy. - The minimum _clog_ is 6 (64 B) and the maximum is 28 (256 MiB). + The minimum _clog_ is 6 (64 B) and the maximum is 29 (524 Mib) on 32-bit platforms + and 30 (1 Gib) on 64-bit platforms. - `searchLog`=_slog_, `slog`=_slog_: Specify the maximum number of searches in a hash chain or a binary tree @@ -422,7 +423,7 @@ The list of available _options_: More searches increases the chance to find a match which usually increases compression ratio but decreases compression speed. - The minimum _slog_ is 1 and the maximum is 26. + The minimum _slog_ is 1 and the maximum is 'windowLog' - 1. - `minMatch`=_mml_, `mml`=_mml_: Specify the minimum searched length of a match in a hash table. @@ -447,7 +448,7 @@ The list of available _options_: For all other strategies, this field has no impact. - The minimum _tlen_ is 0 and the maximum is 999. + The minimum _tlen_ is 0 and the maximum is 128 Kib. - `overlapLog`=_ovlog_, `ovlog`=_ovlog_: Determine `overlapSize`, amount of data reloaded from previous job. @@ -470,7 +471,7 @@ The list of available _options_: Bigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed. - The minimum _lhlog_ is 6 and the maximum is 26 (default: 20). + The minimum _lhlog_ is 6 and the maximum is 30 (default: 20). - `ldmMinMatch`=_lmml_, `lmml`=_lmml_: Specify the minimum searched length of a match for long distance matching. @@ -490,7 +491,7 @@ The list of available _options_: Larger bucket sizes improve collision resolution but decrease compression speed. - The minimum _lblog_ is 0 and the maximum is 8 (default: 3). + The minimum _lblog_ is 1 and the maximum is 8 (default: 3). - `ldmHashRateLog`=_lhrlog_, `lhrlog`=_lhrlog_: Specify the frequency of inserting entries into the long distance matching From 8f0c2d04c8a5ff3e94169ac22c56c9efca7a7154 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 19 Nov 2019 10:03:07 -0800 Subject: [PATCH 086/402] Going back to original flow but removing else return --- lib/compress/zstd_compress.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 6330b882163..064a38ffcfb 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2480,13 +2480,11 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * enough for SuperBlock compression. * In such case, fall back to normal compression. This is possible because * targetCBlockSize is best effort not a guarantee. */ - if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) + if (cSize == ERROR(dstSize_tooSmall) || (dstCapacity - cSize) < 4) { /* We check (dstCapacity - cSize) >= 4 above because we have to make sure * to leave enough room for the checksum that will eventually get added in * the epilogue. Otherwise, we're just going to throw the dstSize_tooSmall * error there instead of here */ - return cSize; - else { BYTE* const ostart = (BYTE*)dst; /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, * compress normally. From e0d6daabac8faf777a9c41877efb3bb5c0e30203 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 19 Nov 2019 11:12:26 -0800 Subject: [PATCH 087/402] Fix Appveyor failure --- lib/decompress/huf_decompress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index fd417088c5c..12c1fce5151 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -191,7 +191,7 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize HUF_DEltX1 D; D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); - rankVal[w] = uEnd; + rankVal[w] = (U32)uEnd; if (length < 4) { /* Use length in the loop bound so the compiler knows it is short. */ for (u = 0; u < length; ++u) From f62cf1fff5dabcfaaa8c85638723bc19842f52f4 Mon Sep 17 00:00:00 2001 From: Sergey Dryabzhinsky Date: Tue, 19 Nov 2019 23:15:28 +0300 Subject: [PATCH 088/402] Fix typo in util.c There must be mtim*e* --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 5d15450d2e1..d3ffc113370 100644 --- a/programs/util.c +++ b/programs/util.c @@ -73,7 +73,7 @@ int UTIL_setFileStat(const char *filename, stat_t *statbuf) { /* (atime, mtime) */ struct timespec timebuf[2] = { {0, UTIME_NOW} }; - timebuf[1] = statbuf->st_mtim; + timebuf[1] = statbuf->st_mtime; res += utimensat(AT_FDCWD, filename, timebuf, 0); } #endif From 612a06eb3ef7f42739ace99fbca6ad63b788d46c Mon Sep 17 00:00:00 2001 From: Sergey Dryabzhinsky Date: Tue, 19 Nov 2019 23:24:00 +0300 Subject: [PATCH 089/402] Update util.c --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index d3ffc113370..aa75ca6d400 100644 --- a/programs/util.c +++ b/programs/util.c @@ -73,7 +73,7 @@ int UTIL_setFileStat(const char *filename, stat_t *statbuf) { /* (atime, mtime) */ struct timespec timebuf[2] = { {0, UTIME_NOW} }; - timebuf[1] = statbuf->st_mtime; + timebuf[1].tv_sec = statbuf->st_mtime; res += utimensat(AT_FDCWD, filename, timebuf, 0); } #endif From e68db76b4bb36106f866c6bd08f6e9a7f2deb884 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 20 Nov 2019 16:36:40 -0800 Subject: [PATCH 090/402] Update .gitignore --- .gitignore | 3 +++ tests/fuzz/.gitignore | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index acd9552be0e..6ad56430467 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ projects/ bin/ .buckd/ buck-out/ +build-* # Other files .directory @@ -43,3 +44,5 @@ _zstdbench/ googletest/ *.d *.vscode +compile_commands.json +.clangd \ No newline at end of file diff --git a/tests/fuzz/.gitignore b/tests/fuzz/.gitignore index 9409cf83731..e2563097e74 100644 --- a/tests/fuzz/.gitignore +++ b/tests/fuzz/.gitignore @@ -2,7 +2,13 @@ corpora block_decompress block_round_trip +dictionary_decompress +dictionary_loader +dictionary_round_trip +simple_compress simple_decompress simple_round_trip stream_decompress stream_round_trip +zstd_frame_info +fuzz-*.log \ No newline at end of file From ac992b35a28cd973d30fcb134b64e3866c5ef515 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 20 Nov 2019 17:26:06 -0800 Subject: [PATCH 091/402] [cmake][tests] Add zstreamtest executable --- build/cmake/tests/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt index 077d824b52d..063260a0ee5 100644 --- a/build/cmake/tests/CMakeLists.txt +++ b/build/cmake/tests/CMakeLists.txt @@ -49,6 +49,9 @@ target_link_libraries(fullbench libzstd_static) add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/fuzzer.c) target_link_libraries(fuzzer libzstd_static) +add_executable(zstreamtest ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/seqgen.c ${TESTS_DIR}/zstreamtest.c) +target_link_libraries(zstreamtest libzstd_static) + if (UNIX) add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c) target_link_libraries(paramgrill libzstd_static m) #m is math library From 659e9f05cf227b14b2d2aafbc29b28184e669f0d Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 20 Nov 2019 18:21:51 -0800 Subject: [PATCH 092/402] Fix null pointer addition --- lib/compress/zstd_compress.c | 24 ++++++++++++------------ lib/compress/zstd_compress_internal.h | 14 ++++++++++++++ lib/compress/zstd_double_fast.c | 4 ++-- lib/compress/zstd_lazy.c | 2 +- lib/compress/zstdmt_compress.c | 4 ++-- lib/decompress/zstd_decompress.c | 19 ++++++++++++------- tests/fuzzer.c | 13 +++++++++++++ tests/zstreamtest.c | 27 +++++++++++++++++++++++++++ 8 files changed, 83 insertions(+), 24 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e9f948170ee..5dacba8cf12 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1336,10 +1336,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms, DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset); if (forceResetIndex == ZSTDirp_reset) { - memset(&ms->window, 0, sizeof(ms->window)); - ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */ - ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ - ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */ + ZSTD_window_init(&ms->window); ZSTD_cwksp_mark_tables_dirty(ws); } @@ -1432,7 +1429,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1); size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize); - ZSTD_indexResetPolicy_e needsIndexReset = ZSTDirp_continue; + ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset; if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) { needsIndexReset = ZSTDirp_reset; @@ -1557,11 +1554,12 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); zc->maxNbLdmSequences = maxNbLdmSeq; - memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window)); + ZSTD_window_init(&zc->ldmState.window); ZSTD_window_clear(&zc->ldmState.window); } DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws)); + zc->initialized = 1; return 0; } @@ -3757,11 +3755,11 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, ZSTD_EndDirective const flushMode) { const char* const istart = (const char*)input->src; - const char* const iend = istart + input->size; - const char* ip = istart + input->pos; + const char* const iend = input->size != 0 ? istart + input->size : istart; + const char* ip = input->pos != 0 ? istart + input->pos : istart; char* const ostart = (char*)output->dst; - char* const oend = ostart + output->size; - char* op = ostart + output->pos; + char* const oend = output->size != 0 ? ostart + output->size : ostart; + char* op = output->pos != 0 ? ostart + output->pos : ostart; U32 someMoreWork = 1; /* check expectations */ @@ -3800,7 +3798,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip); zcs->inBuffPos += loaded; - ip += loaded; + if (loaded != 0) + ip += loaded; if ( (flushMode == ZSTD_e_continue) && (zcs->inBuffPos < zcs->inBuffTarget) ) { /* not enough input to fill full block : stop here */ @@ -3860,7 +3859,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u", (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed); - op += flushed; + if (flushed) + op += flushed; zcs->outBuffFlushedSize += flushed; if (toFlush!=flushed) { /* flush not fully completed, presumably because dst is too small */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 9aec9605fa1..c76189cc148 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -249,6 +249,7 @@ struct ZSTD_CCtx_s { size_t staticSize; SeqCollector seqCollector; int isFirstBlock; + int initialized; seqStore_t seqStore; /* sequences storage ptrs */ ldmState_t ldmState; /* long distance matching state */ @@ -858,6 +859,15 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, } } } } +MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { + memset(window, 0, sizeof(*window)); + window->base = (BYTE const*)""; + window->dictBase = (BYTE const*)""; + window->dictLimit = 1; /* start from 1, so that 1st position is valid */ + window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ + window->nextSrc = window->base + 1; /* see issue #1241 */ +} + /** * ZSTD_window_update(): * Updates the window by appending [src, src + srcSize) to the window. @@ -871,6 +881,10 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, BYTE const* const ip = (BYTE const*)src; U32 contiguous = 1; DEBUGLOG(5, "ZSTD_window_update"); + if (srcSize == 0) + return contiguous; + assert(window->base != NULL); + assert(window->dictBase != NULL); /* Check if blocks follow each other */ if (src != window->nextSrc) { /* not contiguous */ diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index a661a48534d..2e657f7c426 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -96,7 +96,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( dictCParams->hashLog : hBitsL; const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ? dictCParams->chainLog : hBitsS; - const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictStart); + const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart)); DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic"); @@ -271,7 +271,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( U32 const repIndex2 = current2 - offset_2; const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState && repIndex2 < prefixLowestIndex ? - dictBase - dictIndexDelta + repIndex2 : + dictBase + repIndex2 - dictIndexDelta : base + repIndex2; if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 9ad7e03b54c..dd82830eaad 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -660,7 +660,7 @@ ZSTD_compressBlock_lazy_generic( const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ? prefixLowestIndex - (U32)(dictEnd - dictBase) : 0; - const U32 dictAndPrefixLength = (U32)(ip - prefixLowest + dictEnd - dictLowest); + const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); /* init */ ip += (dictAndPrefixLength == 0); diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index b580d94511c..d0542562976 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -490,7 +490,7 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* /* Size the seq pool tables */ ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize)); /* Reset the window */ - ZSTD_window_clear(&serialState->ldmState.window); + ZSTD_window_init(&serialState->ldmState.window); serialState->ldmWindow = serialState->ldmState.window; /* Resize tables and output space if necessary. */ if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) { @@ -1786,7 +1786,7 @@ static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range) BYTE const* const bufferStart = (BYTE const*)buffer.start; BYTE const* const bufferEnd = bufferStart + buffer.capacity; BYTE const* const rangeStart = (BYTE const*)range.start; - BYTE const* const rangeEnd = rangeStart + range.size; + BYTE const* const rangeEnd = range.size != 0 ? rangeStart + range.size : rangeStart; if (rangeStart == NULL || bufferStart == NULL) return 0; diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index dd4591b7be9..d4d42e79447 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -618,7 +618,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, { const BYTE* ip = (const BYTE*)(*srcPtr); BYTE* const ostart = (BYTE* const)dst; - BYTE* const oend = ostart + dstCapacity; + BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart; BYTE* op = ostart; size_t remainingSrcSize = *srcSizePtr; @@ -669,7 +669,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, if (ZSTD_isError(decodedSize)) return decodedSize; if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize); - op += decodedSize; + if (decodedSize != 0) + op += decodedSize; + assert(ip != NULL); ip += cBlockSize; remainingSrcSize -= cBlockSize; if (blockProperties.lastBlock) break; @@ -776,7 +778,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, "error."); if (ZSTD_isError(res)) return res; assert(res <= dstCapacity); - dst = (BYTE*)dst + res; + if (res != 0) + dst = (BYTE*)dst + res; dstCapacity -= res; } moreThan1Frame = 1; @@ -1486,11 +1489,13 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { - const char* const istart = (const char*)(input->src) + input->pos; - const char* const iend = (const char*)(input->src) + input->size; + const char* const src = (const char*)input->src; + const char* const istart = input->pos != 0 ? src + input->pos : src; + const char* const iend = input->size != 0 ? src + input->size : src; const char* ip = istart; - char* const ostart = (char*)(output->dst) + output->pos; - char* const oend = (char*)(output->dst) + output->size; + char* const dst = (char*)output->dst; + char* const ostart = output->pos != 0 ? dst + output->pos : dst; + char* const oend = output->size != 0 ? dst + output->size : dst; char* op = ostart; U32 someMoreWork = 1; diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 427dbff193c..a5991644696 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -490,6 +490,19 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : compress a NULL input with each level : ", testNb++); + { int level = -1; + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + if (!cctx) goto _output_error; + for (level = -1; level <= ZSTD_maxCLevel(); ++level) { + CHECK_Z( ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, level) ); + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, level) ); + CHECK_Z( ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, NULL, 0) ); + } + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 2047d4bd85c..549a4981bbb 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -509,6 +509,33 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : NULL buffers : ", testNb++); + inBuff.src = NULL; + inBuff.size = 0; + inBuff.pos = 0; + outBuff.dst = NULL; + outBuff.size = 0; + outBuff.pos = 0; + CHECK_Z( ZSTD_compressStream(zc, &outBuff, &inBuff) ); + CHECK(inBuff.pos != inBuff.size, "Entire input should be consumed"); + CHECK_Z( ZSTD_endStream(zc, &outBuff) ); + outBuff.dst = (char*)(compressedBuffer); + outBuff.size = compressedBufferSize; + outBuff.pos = 0; + { size_t const r = ZSTD_endStream(zc, &outBuff); + CHECK(r != 0, "Error or some data not flushed (ret=%zu)", r); + } + inBuff.src = outBuff.dst; + inBuff.size = outBuff.pos; + inBuff.pos = 0; + outBuff.dst = NULL; + outBuff.size = 0; + outBuff.pos = 0; + CHECK_Z( ZSTD_initDStream(zd) ); + { size_t const ret = ZSTD_decompressStream(zd, &outBuff, &inBuff); + if (ret != 0) goto _output_error; + } + DISPLAYLEVEL(3, "OK\n"); /* _srcSize compression test */ DISPLAYLEVEL(3, "test%3i : compress_srcSize %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH); CHECK_Z( ZSTD_initCStream_srcSize(zc, 1, CNBufferSize) ); From 0451accab1363778cd1a2fa10660cafdf5143a20 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 21 Nov 2019 13:06:26 -0800 Subject: [PATCH 093/402] Checking noCompressBlock explicitly for rep code confirmation --- lib/compress/zstd_compress.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 064a38ffcfb..f8c64994bf6 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2470,8 +2470,10 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * encode using ZSTD_noCompressSuperBlock writing sub blocks * in uncompressed mode. */ + int usingNoCompressSuperBlock = 0; if (cSize == 0) { cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); + usingNoCompressSuperBlock = 1; /* In compression, there is an assumption that a compressed block is always * within the size of ZSTD_compressBound(). However, SuperBlock compression * can exceed the limit due to overhead of headers from SubBlocks. @@ -2511,7 +2513,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, } } - if (!ZSTD_isError(cSize) && cSize != 0) { + if (!ZSTD_isError(cSize) && !usingNoCompressSuperBlock) { /* confirm repcodes and entropy tables when emitting a compressed block */ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; zc->blockState.prevCBlock = zc->blockState.nextCBlock; From 10bce1919e2a3fb7d64b5ce7b56ecb7a98fd2655 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 21 Nov 2019 13:08:27 -0800 Subject: [PATCH 094/402] Mixed declration fix --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index f8c64994bf6..9211190e499 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2457,6 +2457,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, const void* src, size_t srcSize, U32 lastBlock) { size_t cSize = 0; + int usingNoCompressSuperBlock = 0; DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); @@ -2470,7 +2471,6 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, * encode using ZSTD_noCompressSuperBlock writing sub blocks * in uncompressed mode. */ - int usingNoCompressSuperBlock = 0; if (cSize == 0) { cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); usingNoCompressSuperBlock = 1; From 707a12c419ecdb5d1f91d9bc18703b8bbead2585 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 22 Nov 2019 17:25:36 -0800 Subject: [PATCH 095/402] Test enough room for checksum in superblock --- tests/fuzzer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index a61667ed374..8dbaa33847f 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -427,7 +427,6 @@ static int basicUnitTests(U32 const seed, double compressibility) } } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : decompress with null dict : ", testNb++); { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); { size_t const r = ZSTD_decompress_usingDict(dctx, @@ -490,6 +489,19 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d: superblock enough room for checksum : ", testNb++) + { + /* This tests whether or not we leave enough room for the checksum at the end + * of the dst buffer. The bug that motivated this test was found by the + * stream_round_trip fuzzer but this crashes for the same reason and is + * far more compact than re-creating the stream_round_trip fuzzer's code path */ + ZSTD_CCtx *cctx = ZSTD_createCCtx(); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 64); + assert(!ZSTD_isError(ZSTD_compress2(cctx, compressedBuffer, 1339, CNBuffer, 1278))); + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d : check CCtx size after compressing empty input : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); size_t const r = ZSTD_compressCCtx(cctx, compressedBuffer, compressedBufferSize, NULL, 0, 19); From 762a0dfc459ab67dba67aa02c05a2280cfa3f0d9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 22 Nov 2019 17:32:07 -0800 Subject: [PATCH 096/402] minor update to travis script many tests used to be run on Trusty platform, they are now run on _current_ platform, and now many test titles are incorrect. Fixed. --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97f95a60ebf..e17dba64575 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ matrix: script: - make check - - name: Trusty (Test All) + - name: make test (complete) script: - make test @@ -80,43 +80,43 @@ matrix: - make clean - make -j check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - - name: Trusty (CMake) + - name: cmake test script: - make cmakebuild - - name: Trusty (Static Analyze) + - name: static analyzer scanbuild script: - make staticAnalyze - - name: Trusty (gcc-8 + ASan + UBSan + Fuzz Test) + - name: gcc-8 + ASan + UBSan + Fuzz Test script: - make gcc8install - CC=gcc-8 make clean uasan-fuzztest - - name: Trusty (gcc-6 + ASan + UBSan + Fuzz Test 32bit) + - name: gcc-6 + ASan + UBSan + Fuzz Test 32bit script: - make gcc6install libc6install - CC=gcc-6 CFLAGS="-O2 -m32" make uasan-fuzztest # can complain about pointer overflow - - name: Trusty (clang-3.8 + MSan + Fuzz Test) + - name: clang-3.8 + MSan + Fuzz Test script: - make clang38install - CC=clang-3.8 make clean msan-fuzztest - - name: Trusty (ASan + UBSan + MSan + Regression Test) + - name: ASan + UBSan + MSan + Regression Test script: - make -j uasanregressiontest - make clean - make -j msanregressiontest - - name: Trusty (Valgrind + Fuzz Test Stack Mode) + - name: Valgrind + Fuzz Test Stack Mode script: - make valgrindinstall - make -C tests clean valgrindTest - make clean - make -C tests test-fuzzer-stackmode - - name: Trusty (ARM + Fuzz Test) + - name: Qemu ARM emulation + Fuzz Test script: - make arminstall - make armfuzz @@ -127,12 +127,12 @@ matrix: - make arminstall - make aarch64fuzz - - name: Trusty (PPC + Fuzz Test) + - name: PPC + Fuzz Test script: - make ppcinstall - make ppcfuzz - - name: Trusty (Versions Compatibility Test) + - name: Versions Compatibility Test script: - make -C tests versionsTest From 7aaac3f69c1e0102099c192639017e660e88b4bf Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 10:35:36 -0800 Subject: [PATCH 097/402] fix #1904 /dev/null permissions were modified when using sudo rights. This fixes this bug during decompression. More importantly, this patch adds a test, triggered in TravisCI, ensuring unaltered /dev/null permissions. --- .travis.yml | 3 ++- programs/fileio.c | 12 ++++++++++-- tests/playTests.sh | 27 +++++++++++++++++++-------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index e17dba64575..ec1adab0302 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,8 @@ matrix: - name: make test (complete) script: - - make test + # DEVNULLRIGHTS : will request sudo rights to test permissions on /dev/null + - DEVNULLRIGHTS=test make test - name: gcc-6 + gcc-7 compilation script: diff --git a/programs/fileio.c b/programs/fileio.c index 9833767282e..60b704537f4 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -609,7 +609,10 @@ FIO_openDstFile(FIO_prefs_t* const prefs, { FILE* const f = fopen( dstFileName, "wb" ); if (f == NULL) { DISPLAYLEVEL(1, "zstd: %s: %s\n", dstFileName, strerror(errno)); - } else if(srcFileName != NULL && strcmp (srcFileName, stdinmark)) { + } else if (srcFileName != NULL + && strcmp (srcFileName, stdinmark) + && strcmp(dstFileName, nulmark) ) { + /* reduce rights on newly created dst file while compression is ongoing */ chmod(dstFileName, 00600); } return f; @@ -1393,7 +1396,7 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, assert(ress.srcFile != NULL); if (ress.dstFile == NULL) { closeDstFile = 1; - DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s", dstFileName); + DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: opening dst: %s \n", dstFileName); ress.dstFile = FIO_openDstFile(prefs, srcFileName, dstFileName); if (ress.dstFile==NULL) return 1; /* could not open dstFileName */ /* Must only be added after FIO_openDstFile() succeeds. @@ -1415,6 +1418,7 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, clearHandler(); + DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: closing dst: %s \n", dstFileName); if (fclose(dstFile)) { /* error closing dstFile */ DISPLAYLEVEL(1, "zstd: %s: %s \n", dstFileName, strerror(errno)); result=1; @@ -1427,7 +1431,10 @@ static int FIO_compressFilename_dstFile(FIO_prefs_t* const prefs, } else if ( strcmp(dstFileName, stdoutmark) && strcmp(dstFileName, nulmark) && transfer_permissions) { + DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: transfering permissions into dst: %s \n", dstFileName); UTIL_setFileStat(dstFileName, &statbuf); + } else { + DISPLAYLEVEL(6, "FIO_compressFilename_dstFile: do not transfer permissions into dst: %s \n", dstFileName); } } @@ -1462,6 +1469,7 @@ FIO_compressFilename_srcFile(FIO_prefs_t* const prefs, int compressionLevel) { int result; + DISPLAYLEVEL(6, "FIO_compressFilename_srcFile: %s \n", srcFileName); /* ensure src is not a directory */ if (UTIL_isDirectory(srcFileName)) { diff --git a/tests/playTests.sh b/tests/playTests.sh index 4bb75d2f35c..6359076c51e 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -220,13 +220,12 @@ $ZSTD tmp -c --compress-literals -19 | $ZSTD -t $ZSTD -b --fast=1 -i0e1 tmp --compress-literals $ZSTD -b --fast=1 -i0e1 tmp --no-compress-literals -println "test: --exclude-compressed flag" +println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir ./datagen $size > precompressedFilterTestDir/input.5 ./datagen $size > precompressedFilterTestDir/input.6 $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir -sleep 5 ./datagen $size > precompressedFilterTestDir/input.7 ./datagen $size > precompressedFilterTestDir/input.8 $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir @@ -251,7 +250,7 @@ test -f precompressedFilterTestDir/input.5.zst.zst test -f precompressedFilterTestDir/input.6.zst.zst println "Test completed" -println "test : file removal" +println "\n===> file removal" $ZSTD -f --rm tmp test ! -f tmp # tmp should no longer be present $ZSTD -f -d --rm tmp.zst @@ -278,13 +277,16 @@ $ZSTD -f tmp && die "attempt to compress a non existing file" test -f tmp.zst # destination file should still be present rm -rf tmp* # may also erase tmp* directory from previous failed run -println "\n===> decompression only tests " -dd bs=1 count=1048576 if=/dev/zero of=tmp +println "\n===> decompression only tests " +# the following test verifies that the decoder is compatible with RLE as first block +# older versions of zstd cli are not able to decode such corner case. +# As a consequence, the zstd cli do not generate them, to maintain compatibility with older versions. +dd bs=1048576 count=1 if=/dev/zero of=tmp $ZSTD -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst" $DIFF -s tmp1 tmp rm tmp* -println "test : compress multiple files" +println "\m===> compress multiple files" println hello > tmp1 println world > tmp2 $ZSTD tmp1 tmp2 -o "$INTOVOID" -f @@ -306,7 +308,17 @@ if [ "$?" -eq 139 ]; then fi rm tmp* -println "test : compress multiple files into an output directory, --output-dir-flat" +if [ -n "$DEVNULLRIGHTS" ] +then + # these tests requires sudo rights, which is uncommon. + # they are only triggered if DEVNULLRIGHTS macro is defined. + println "\n===> checking /dev/null permissions are unaltered " + ./datagen > tmp + sudo $ZSTD tmp -o $INTOVOID # sudo rights could modify /dev/null permissions + ls -las $INTOVOID | grep "rw-rw-rw-" +fi + +println "\n===> compress multiple files into an output directory, --output-dir-flat" println henlo > tmp1 mkdir tmpInputTestDir mkdir tmpInputTestDir/we @@ -352,7 +364,6 @@ $ZSTD -dcf tmp1 println "\n===> frame concatenation " - println "hello " > hello.tmp println "world!" > world.tmp cat hello.tmp world.tmp > helloworld.tmp From 60db21a677a59ad0fb5910b87355ad161a216a47 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 10:53:03 -0800 Subject: [PATCH 098/402] added decompression into /dev/null tests --- tests/playTests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/playTests.sh b/tests/playTests.sh index 6359076c51e..2955251143c 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -315,6 +315,10 @@ then println "\n===> checking /dev/null permissions are unaltered " ./datagen > tmp sudo $ZSTD tmp -o $INTOVOID # sudo rights could modify /dev/null permissions + sudo $ZSTD tmp -c > $INTOVOID + $ZSTD tmp -f -o tmp.zst + sudo $ZSTD -d tmp.zst -c > $INTOVOID + sudo $ZSTD -d tmp.zst -o $INTOVOID ls -las $INTOVOID | grep "rw-rw-rw-" fi From 9a22140ef46195a6c7f15ce66f5fe98320ed4727 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 13:45:22 -0800 Subject: [PATCH 099/402] created UTIL_chmod() protecting "/dev/null" from having its permissions changed. also : minor : improved consistency of util.h API --- programs/fileio.c | 8 +++----- programs/util.c | 44 +++++++++++++++++++++++++++++++------------- programs/util.h | 42 +++++++++++++++++------------------------- programs/zstdcli.c | 21 +++++++-------------- 4 files changed, 58 insertions(+), 57 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 60b704537f4..a45dedc464f 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -502,7 +502,7 @@ static int FIO_remove(const char* path) #if defined(_WIN32) || defined(WIN32) /* windows doesn't allow remove read-only files, * so try to make it writable first */ - chmod(path, _S_IWRITE); + UTIL_chmod(path, _S_IWRITE); #endif return remove(path); } @@ -526,9 +526,7 @@ static FILE* FIO_openSrcFile(const char* srcFileName) } if (!UTIL_isRegularFile(srcFileName) -#ifndef _MSC_VER - && !UTIL_isFIFO(srcFileName) -#endif /* _MSC_VER */ + && !UTIL_isFIFO(srcFileName) ) { DISPLAYLEVEL(1, "zstd: %s is not a regular file -- ignored \n", srcFileName); @@ -613,7 +611,7 @@ FIO_openDstFile(FIO_prefs_t* const prefs, && strcmp (srcFileName, stdinmark) && strcmp(dstFileName, nulmark) ) { /* reduce rights on newly created dst file while compression is ongoing */ - chmod(dstFileName, 00600); + UTIL_chmod(dstFileName, 00600); } return f; } diff --git a/programs/util.c b/programs/util.c index aa75ca6d400..cb177a3c75b 100644 --- a/programs/util.c +++ b/programs/util.c @@ -24,6 +24,21 @@ extern "C" { #include /* needed for _mkdir in windows */ #endif +#if defined(_MSC_VER) + #define chmod _chmod +#endif + + +/*-************************************* +* Constants +***************************************/ +#define LIST_SIZE_INCREASE (8*1024) + + +/*-************************************* +* Functions +***************************************/ + int UTIL_fileExist(const char* filename) { stat_t statbuf; @@ -54,6 +69,13 @@ int UTIL_getFileStat(const char* infilename, stat_t *statbuf) return 1; } +/* like chmod, but avoid changing permission of /dev/null */ +int UTIL_chmod(char const* filename, mode_t permissions) +{ + if (!strcmp(filename, "/dev/null")) return 0; /* pretend success, but don't change anything */ + return chmod(filename, permissions); +} + int UTIL_setFileStat(const char *filename, stat_t *statbuf) { int res = 0; @@ -82,21 +104,20 @@ int UTIL_setFileStat(const char *filename, stat_t *statbuf) res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */ #endif - res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */ + res += UTIL_chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */ errno = 0; return -res; /* number of errors is returned */ } -U32 UTIL_isDirectory(const char* infilename) +int UTIL_isDirectory(const char* infilename) { - int r; stat_t statbuf; #if defined(_MSC_VER) - r = _stat64(infilename, &statbuf); + int const r = _stat64(infilename, &statbuf); if (!r && (statbuf.st_mode & _S_IFDIR)) return 1; #else - r = stat(infilename, &statbuf); + int const r = stat(infilename, &statbuf); if (!r && S_ISDIR(statbuf.st_mode)) return 1; #endif return 0; @@ -126,28 +147,25 @@ int UTIL_isSameFile(const char* fName1, const char* fName2) #endif } -#ifndef _MSC_VER -/* Using this to distinguish named pipes */ -U32 UTIL_isFIFO(const char* infilename) +/* UTIL_isFIFO : distinguish named pipes */ +int UTIL_isFIFO(const char* infilename) { /* macro guards, as defined in : https://linux.die.net/man/2/lstat */ #if PLATFORM_POSIX_VERSION >= 200112L stat_t statbuf; - int r = UTIL_getFileStat(infilename, &statbuf); + int const r = UTIL_getFileStat(infilename, &statbuf); if (!r && S_ISFIFO(statbuf.st_mode)) return 1; #endif (void)infilename; return 0; } -#endif -U32 UTIL_isLink(const char* infilename) +int UTIL_isLink(const char* infilename) { /* macro guards, as defined in : https://linux.die.net/man/2/lstat */ #if PLATFORM_POSIX_VERSION >= 200112L - int r; stat_t statbuf; - r = lstat(infilename, &statbuf); + int const r = lstat(infilename, &statbuf); if (!r && S_ISLNK(statbuf.st_mode)) return 1; #endif (void)infilename; diff --git a/programs/util.h b/programs/util.h index 1f524f2934a..46e1f21f5a0 100644 --- a/programs/util.h +++ b/programs/util.h @@ -30,12 +30,12 @@ extern "C" { # include /* _chmod */ #else # include /* chown, stat */ -#if PLATFORM_POSIX_VERSION < 200809L -# include /* utime */ -#else -# include /* AT_FDCWD */ -# include /* utimensat */ -#endif +# if PLATFORM_POSIX_VERSION < 200809L +# include /* utime */ +# else +# include /* AT_FDCWD */ +# include /* utimensat */ +# endif #endif #include /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */ #include "mem.h" /* U32, U64 */ @@ -85,12 +85,6 @@ extern "C" { #endif -/*-************************************* -* Constants -***************************************/ -#define LIST_SIZE_INCREASE (8*1024) - - /*-**************************************** * Compiler specifics ******************************************/ @@ -120,7 +114,6 @@ extern int g_utilDisplayLevel; * File functions ******************************************/ #if defined(_MSC_VER) - #define chmod _chmod typedef struct __stat64 stat_t; #else typedef struct stat stat_t; @@ -129,30 +122,29 @@ extern int g_utilDisplayLevel; int UTIL_fileExist(const char* filename); int UTIL_isRegularFile(const char* infilename); -int UTIL_setFileStat(const char* filename, stat_t* statbuf); -U32 UTIL_isDirectory(const char* infilename); -int UTIL_getFileStat(const char* infilename, stat_t* statbuf); +int UTIL_isDirectory(const char* infilename); int UTIL_isSameFile(const char* file1, const char* file2); -int UTIL_compareStr(const void *p1, const void *p2); int UTIL_isCompressedFile(const char* infilename, const char *extensionList[]); -const char* UTIL_getFileExtension(const char* infilename); +int UTIL_isLink(const char* infilename); +int UTIL_isFIFO(const char* infilename); -#ifndef _MSC_VER -U32 UTIL_isFIFO(const char* infilename); -#endif -U32 UTIL_isLink(const char* infilename); #define UTIL_FILESIZE_UNKNOWN ((U64)(-1)) U64 UTIL_getFileSize(const char* infilename); - U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles); +int UTIL_getFileStat(const char* infilename, stat_t* statbuf); +int UTIL_setFileStat(const char* filename, stat_t* statbuf); +int UTIL_chmod(char const* filename, mode_t permissions); /*< like chmod, but avoid changing permission of /dev/null */ +int UTIL_compareStr(const void *p1, const void *p2); +const char* UTIL_getFileExtension(const char* infilename); + /* * A modified version of realloc(). * If UTIL_realloc() fails the original block is freed. */ -UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size) +UTIL_STATIC void* UTIL_realloc(void* ptr, size_t size) { - void *newptr = realloc(ptr, size); + void* const newptr = realloc(ptr, size); if (newptr) return newptr; free(ptr); return NULL; diff --git a/programs/zstdcli.c b/programs/zstdcli.c index cd6b40bc089..ad2bbbd88eb 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1005,16 +1005,13 @@ int main(int argCount, const char* argv[]) if (!followLinks) { unsigned u; for (u=0, fileNamesNb=0; u 0) CLEAN_RETURN(1); filenameIdx = fileNamesNb; @@ -1027,8 +1024,7 @@ int main(int argCount, const char* argv[]) free((void*)filenameTable); filenameTable = extendedFileList; filenameIdx = fileNamesNb; - } - } + } } #else (void)followLinks; #endif @@ -1074,18 +1070,15 @@ int main(int argCount, const char* argv[]) DISPLAYLEVEL(3, "Benchmarking %s \n", filenameTable[i]); for(c = cLevel; c <= cLevelLast; c++) { BMK_benchFilesAdvanced(&filenameTable[i], 1, dictFileName, c, &compressionParams, g_displayLevel, &benchParams); - } - } + } } } else { for(; cLevel <= cLevelLast; cLevel++) { BMK_benchFilesAdvanced(filenameTable, filenameIdx, dictFileName, cLevel, &compressionParams, g_displayLevel, &benchParams); - } - } + } } } else { for(; cLevel <= cLevelLast; cLevel++) { BMK_syntheticTest(cLevel, compressibility, &compressionParams, g_displayLevel, &benchParams); - } - } + } } #else (void)bench_nbSeconds; (void)blockSize; (void)setRealTimePrio; (void)separateFiles; (void)compressibility; From b1de3ecdd503ac0625c68f4819f9ab9c177e44ec Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 13:59:35 -0800 Subject: [PATCH 100/402] fix mode_t on Windows --- programs/util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/util.h b/programs/util.h index 46e1f21f5a0..e67faba5c6a 100644 --- a/programs/util.h +++ b/programs/util.h @@ -115,6 +115,7 @@ extern int g_utilDisplayLevel; ******************************************/ #if defined(_MSC_VER) typedef struct __stat64 stat_t; + typedef int mode_t; #else typedef struct stat stat_t; #endif From 9a3de0a535b0b3bf90c522280f3124e47d6bf0d5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 15:34:55 -0800 Subject: [PATCH 101/402] changed name from createX to assembleX shows that the resulting object just takes ownership of provided buffer. --- contrib/largeNbDicts/largeNbDicts.c | 4 ++-- programs/util.c | 12 ++++++------ programs/util.h | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/largeNbDicts/largeNbDicts.c b/contrib/largeNbDicts/largeNbDicts.c index 0038e2041f6..121cf2f9916 100644 --- a/contrib/largeNbDicts/largeNbDicts.c +++ b/contrib/largeNbDicts/largeNbDicts.c @@ -770,7 +770,7 @@ int main (int argc, const char** argv) if (argc < 2) return bad_usage(exeName); - const char** nameTable = (const char**)malloc(argc * sizeof(const char*)); + const char** nameTable = (const char**)malloc((size_t)argc * sizeof(const char*)); assert(nameTable != NULL); unsigned nameIdx = 0; @@ -805,7 +805,7 @@ int main (int argc, const char** argv) #endif filenameTable = UTIL_createExpandedFNT(nameTable, nameIdx, 1 /* follow_links */); } else { - filenameTable = UTIL_createFileNamesTable(nameTable, nameIdx, NULL); + filenameTable = UTIL_assembleFileNamesTable(nameTable, nameIdx, NULL); nameTable = NULL; /* UTIL_createFileNamesTable() takes ownership of nameTable */ } diff --git a/programs/util.c b/programs/util.c index 7839799da5b..ef1ee7b15b4 100644 --- a/programs/util.c +++ b/programs/util.c @@ -323,12 +323,12 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) } } assert(pos <= bufSize); - return UTIL_createFileNamesTable(filenamesTable, nbFiles, buf); + return UTIL_assembleFileNamesTable(filenamesTable, nbFiles, buf); } } FileNamesTable* -UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf) +UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf) { FileNamesTable* const table = (FileNamesTable*) malloc(sizeof(*table)); if(!table) return NULL; @@ -352,7 +352,7 @@ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize) const char** const fnTable = (const char**)malloc(tableSize * sizeof(*fnTable)); FileNamesTable* fnt; if (fnTable==NULL) return NULL; - fnt = UTIL_createFileNamesTable(fnTable, tableSize, NULL); + fnt = UTIL_assembleFileNamesTable(fnTable, tableSize, NULL); fnt->tableSize = 0; /* the table is empty */ return fnt; } @@ -381,7 +381,7 @@ UTIL_mergeFileNamesTable(FileNamesTable* table1, FileNamesTable* table2) size_t newTotalTableSize; char* buf; - FileNamesTable* const newTable = UTIL_createFileNamesTable(NULL, 0, NULL); + FileNamesTable* const newTable = UTIL_assembleFileNamesTable(NULL, 0, NULL); CONTROL( newTable != NULL ); newTotalTableSize = getTotalTableSize(table1) + getTotalTableSize(table2); @@ -630,7 +630,7 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) pos += strlen(fileNamesTable[ifnNb]) + 1; } - return UTIL_createFileNamesTable(fileNamesTable, nbFiles, buf); + return UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); } } @@ -648,7 +648,7 @@ FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFile const char** const newFNTable = (const char**)malloc(sizeof_FNTable); if (newFNTable==NULL) return NULL; memcpy((void*)newFNTable, filenames, sizeof_FNTable); /* void* : mitigate a Visual compiler bug or limitation */ - return UTIL_createFileNamesTable(newFNTable, nbFilenames, NULL); + return UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL); } diff --git a/programs/util.h b/programs/util.h index 91a449a679a..14e5b4948a4 100644 --- a/programs/util.h +++ b/programs/util.h @@ -175,13 +175,13 @@ typedef struct FileNamesTable* UTIL_createFileNamesTable_fromFileName(const char* inputFileName); -/*! UTIL_createFileNamesTable() : +/*! UTIL_assembleFileNamesTable() : * This function takes ownership of its arguments, @filenames and @buf, * and store them inside the created object. * @return : FileNamesTable*, or NULL, if allocation fails. */ FileNamesTable* -UTIL_createFileNamesTable(const char** filenames, size_t tableSize, char* buf); +UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf); /*! UTIL_freeFileNamesTable() : * This function is compatible with NULL argument and never fails. From 5e657aca905a767e0eed5ab692f6e1b30024d3f7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 25 Nov 2019 15:50:58 -0800 Subject: [PATCH 102/402] silence scan-build false positive blind attempt --- programs/util.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/programs/util.c b/programs/util.c index ef1ee7b15b4..3ca404b34a1 100644 --- a/programs/util.c +++ b/programs/util.c @@ -629,8 +629,19 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) if (buf + pos > bufend) { free(buf); free((void*)fileNamesTable); return NULL; } pos += strlen(fileNamesTable[ifnNb]) + 1; } - - return UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); + { FileNamesTable* const fnt = UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); +#ifdef __clang_analyzer__ + /* scan-build does not understand ownership transfer. + * In _some_ versions, it believes that there is a leak of @buf and @fileNamesTable + * on leaving the function, which is not the case, + * as they are referenced inside the object created by UTIL_assembleFileNamesTable(). + * In order to silence this false warning, let's "pretend" that these memory objects are freed. + * This directive is only read by scan-build, due to __clang_analyzer__ macros */ + free(buf); + free(fileNamesTable); +#endif + return fnt; + } } } @@ -648,7 +659,18 @@ FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFile const char** const newFNTable = (const char**)malloc(sizeof_FNTable); if (newFNTable==NULL) return NULL; memcpy((void*)newFNTable, filenames, sizeof_FNTable); /* void* : mitigate a Visual compiler bug or limitation */ - return UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL); + { FileNamesTable* const fnt = UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL);; +#ifdef __clang_analyzer__ + /* scan-build does not understand ownership transfer. + * In _some_ versions, it believes that there is a leak of @newFNTable + * on leaving the function, which is not the case, + * as they are referenced inside the object created by UTIL_assembleFileNamesTable(). + * In order to silence this false warning, let's "pretend" that these memory objects are freed. + * This directive is only read by scan-build, due to __clang_analyzer__ macros */ + free(newFNTable); +#endif + return fnt; + } } From 718f00ff6fe42db7e6ba09a7f7992b3e85283f77 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 25 Nov 2019 18:26:19 -0800 Subject: [PATCH 103/402] Optimize decompression speed for gcc and clang (#1892) * Optimize `ZSTD_decodeSequence()` * Optimize Huffman decoding * Optimize `ZSTD_decompressSequences()` * Delete `ZSTD_decodeSequenceLong()` --- lib/common/bitstream.h | 23 ++- lib/common/compiler.h | 13 ++ lib/decompress/huf_decompress.c | 50 ++++-- lib/decompress/zstd_decompress_block.c | 236 +++++++++++-------------- 4 files changed, 174 insertions(+), 148 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index 1c294b80d13..fe3148eebd0 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -48,6 +48,7 @@ extern "C" { * Dependencies ******************************************/ #include "mem.h" /* unaligned access routines */ +#include "compiler.h" /* UNLIKELY() */ #include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */ #include "error_private.h" /* error codes and messages */ @@ -411,6 +412,23 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) return value; } +/*! BIT_reloadDStreamFast() : + * Similar to BIT_reloadDStream(), but with two differences: + * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold! + * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this + * point you must use BIT_reloadDStream() to reload. + */ +MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD) +{ + if (UNLIKELY(bitD->ptr < bitD->limitPtr)) + return BIT_DStream_overflow; + assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8); + bitD->ptr -= bitD->bitsConsumed >> 3; + bitD->bitsConsumed &= 7; + bitD->bitContainer = MEM_readLEST(bitD->ptr); + return BIT_DStream_unfinished; +} + /*! BIT_reloadDStream() : * Refill `bitD` from buffer previously set in BIT_initDStream() . * This function is safe, it guarantees it will not read beyond src buffer. @@ -422,10 +440,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) return BIT_DStream_overflow; if (bitD->ptr >= bitD->limitPtr) { - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = MEM_readLEST(bitD->ptr); - return BIT_DStream_unfinished; + return BIT_reloadDStreamFast(bitD); } if (bitD->ptr == bitD->start) { if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 1877a0c1d9b..228845aa923 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -146,6 +146,19 @@ # define DONT_VECTORIZE #endif +/* Tell the compiler that a branch is likely or unlikely. + * Only use these macros if it causes the compiler to generate better code. + * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc + * and clang, please do. + */ +#if defined(__GNUC__) +#define LIKELY(x) (__builtin_expect((x), 1)) +#define UNLIKELY(x) (__builtin_expect((x), 0)) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + /* disable warnings */ #ifdef _MSC_VER /* Visual Studio */ # include /* For Visual 2005 */ diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 12c1fce5151..732e1c93bfc 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -294,6 +294,7 @@ HUF_decompress4X1_usingDTable_internal_body( { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; + BYTE* const olimit = oend - 3; const void* const dtPtr = DTable + 1; const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; @@ -318,9 +319,9 @@ HUF_decompress4X1_usingDTable_internal_body( BYTE* op2 = opStart2; BYTE* op3 = opStart3; BYTE* op4 = opStart4; - U32 endSignal = BIT_DStream_unfinished; DTableDesc const dtd = HUF_getDTableDesc(DTable); U32 const dtLog = dtd.tableLog; + U32 endSignal = 1; if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); @@ -329,8 +330,7 @@ HUF_decompress4X1_usingDTable_internal_body( CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) { + for ( ; (endSignal) & (op4 < olimit) ; ) { HUF_DECODE_SYMBOLX1_2(op1, &bitD1); HUF_DECODE_SYMBOLX1_2(op2, &bitD2); HUF_DECODE_SYMBOLX1_2(op3, &bitD3); @@ -347,10 +347,10 @@ HUF_decompress4X1_usingDTable_internal_body( HUF_DECODE_SYMBOLX1_0(op2, &bitD2); HUF_DECODE_SYMBOLX1_0(op3, &bitD3); HUF_DECODE_SYMBOLX1_0(op4, &bitD4); - BIT_reloadDStream(&bitD1); - BIT_reloadDStream(&bitD2); - BIT_reloadDStream(&bitD3); - BIT_reloadDStream(&bitD4); + endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; } /* check corruption */ @@ -769,7 +769,6 @@ HUF_decompress1X2_usingDTable_internal_body( return dstSize; } - FORCE_INLINE_TEMPLATE size_t HUF_decompress4X2_usingDTable_internal_body( void* dst, size_t dstSize, @@ -781,6 +780,7 @@ HUF_decompress4X2_usingDTable_internal_body( { const BYTE* const istart = (const BYTE*) cSrc; BYTE* const ostart = (BYTE*) dst; BYTE* const oend = ostart + dstSize; + BYTE* const olimit = oend - (sizeof(size_t)-1); const void* const dtPtr = DTable+1; const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; @@ -805,7 +805,7 @@ HUF_decompress4X2_usingDTable_internal_body( BYTE* op2 = opStart2; BYTE* op3 = opStart3; BYTE* op4 = opStart4; - U32 endSignal; + U32 endSignal = 1; DTableDesc const dtd = HUF_getDTableDesc(DTable); U32 const dtLog = dtd.tableLog; @@ -816,8 +816,29 @@ HUF_decompress4X2_usingDTable_internal_body( CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); /* 16-32 symbols per loop (4-8 symbols per stream) */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) { + for ( ; (endSignal) & (op4 < olimit); ) { +#ifdef __clang__ + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_1(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_0(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_1(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_0(op2, &bitD2); + endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_1(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_0(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_1(op4, &bitD4); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_0(op4, &bitD4); + endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; +#else HUF_DECODE_SYMBOLX2_2(op1, &bitD1); HUF_DECODE_SYMBOLX2_2(op2, &bitD2); HUF_DECODE_SYMBOLX2_2(op3, &bitD3); @@ -834,8 +855,11 @@ HUF_decompress4X2_usingDTable_internal_body( HUF_DECODE_SYMBOLX2_0(op2, &bitD2); HUF_DECODE_SYMBOLX2_0(op3, &bitD3); HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; +#endif } /* check corruption */ diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 767e5f9a0b0..ce43c525545 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -715,7 +715,7 @@ size_t ZSTD_execSequence(BYTE* op, /* Errors and uncommon cases handled here. */ assert(oLitEnd < oMatchEnd); - if (iLitEnd > litLimit || oMatchEnd > oend_w) + if (UNLIKELY(iLitEnd > litLimit || oMatchEnd > oend_w)) return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */ @@ -729,7 +729,7 @@ size_t ZSTD_execSequence(BYTE* op, */ assert(WILDCOPY_OVERLENGTH >= 16); ZSTD_copy16(op, (*litPtr)); - if (sequence.litLength > 16) { + if (UNLIKELY(sequence.litLength > 16)) { ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap); } op = oLitEnd; @@ -738,7 +738,7 @@ size_t ZSTD_execSequence(BYTE* op, /* Copy Match */ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { /* offset beyond prefix -> go into extDict */ - RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected); + RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected); match = dictEnd + (match - prefixStart); if (match + sequence.matchLength <= dictEnd) { memmove(oLitEnd, match, sequence.matchLength); @@ -760,7 +760,7 @@ size_t ZSTD_execSequence(BYTE* op, /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy * without overlap checking. */ - if (sequence.offset >= WILDCOPY_VECLEN) { + if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) { /* We bet on a full wildcopy for matches, since we expect matches to be * longer than literals (in general). In silesia, ~10% of matches are longer * than 16 bytes. @@ -802,6 +802,14 @@ ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD) DStatePtr->state = DInfo.nextState + lowBits; } +FORCE_INLINE_TEMPLATE void +ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD_seqSymbol const DInfo) +{ + U32 const nbBits = DInfo.nbBits; + size_t const lowBits = BIT_readBits(bitD, nbBits); + DStatePtr->state = DInfo.nextState + lowBits; +} + /* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1) * bits before reloading. This value is the maximum number of bytes we read @@ -813,25 +821,26 @@ ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD) : 0) typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e; +typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e; -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG FORCE_INLINE_TEMPLATE seq_t -ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets) +ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch) { seq_t seq; - U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits; - U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits; - U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits; - U32 const totalBits = llBits+mlBits+ofBits; - U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue; - U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue; - U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue; + ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state]; + ZSTD_seqSymbol const mlDInfo = seqState->stateML.table[seqState->stateML.state]; + ZSTD_seqSymbol const ofDInfo = seqState->stateOffb.table[seqState->stateOffb.state]; + U32 const llBase = llDInfo.baseValue; + U32 const mlBase = mlDInfo.baseValue; + U32 const ofBase = ofDInfo.baseValue; + BYTE const llBits = llDInfo.nbAdditionalBits; + BYTE const mlBits = mlDInfo.nbAdditionalBits; + BYTE const ofBits = ofDInfo.nbAdditionalBits; + BYTE const totalBits = llBits+mlBits+ofBits; /* sequence */ { size_t offset; - if (!ofBits) - offset = 0; - else { + if (ofBits > 1) { ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); assert(ofBits <= MaxOff); @@ -845,53 +854,89 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets) offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); } - } - - if (ofBits <= 1) { - offset += (llBase==0); - if (offset) { - size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ - if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset = temp; - } else { /* offset == 0 */ - offset = seqState->prevOffset[0]; - } - } else { seqState->prevOffset[2] = seqState->prevOffset[1]; seqState->prevOffset[1] = seqState->prevOffset[0]; seqState->prevOffset[0] = offset; - } + } else { + U32 const ll0 = (llBase == 0); + if (LIKELY((ofBits == 0))) { + if (LIKELY(!ll0)) + offset = seqState->prevOffset[0]; + else { + offset = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset; + } + } else { + offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1); + { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; + temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ + if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset = temp; + } } } seq.offset = offset; } - seq.matchLength = mlBase - + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/) : 0); /* <= 16 bits */ + seq.matchLength = mlBase; + if (mlBits > 0) + seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/); + if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) BIT_reloadDStream(&seqState->DStream); - if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) + if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) BIT_reloadDStream(&seqState->DStream); /* Ensure there are enough bits to read the rest of data in 64-bit mode. */ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); - seq.litLength = llBase - + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits/*>0*/) : 0); /* <= 16 bits */ + seq.litLength = llBase; + if (llBits > 0) + seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/); + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u", (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); - /* ANS state update */ - ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ - ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ + if (prefetch == ZSTD_p_prefetch) { + size_t const pos = seqState->pos + seq.litLength; + const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart; + seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. + * No consequence though : no memory access will occur, offset is only used for prefetching */ + seqState->pos = pos + seq.matchLength; + } + + /* ANS state update + * gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo(). + * clang-9.2.0 does 7% worse with ZSTD_updateFseState(). + * Naturally it seems like ZSTD_updateFseStateWithDInfo() should be the + * better option, so it is the default for other compilers. But, if you + * measure that it is worse, please put up a pull request. + */ + { +#if defined(__GNUC__) && !defined(__clang__) + const int kUseUpdateFseState = 1; +#else + const int kUseUpdateFseState = 0; +#endif + if (kUseUpdateFseState) { + ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ + ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ + ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ + } else { + ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llDInfo); /* <= 9 bits */ + ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlDInfo); /* <= 9 bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ + ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofDInfo); /* <= 8 bits */ + } + } return seq; } +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG FORCE_INLINE_TEMPLATE size_t DONT_VECTORIZE ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, @@ -914,6 +959,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, /* Regen sequences */ if (nbSeq) { seqState_t seqState; + size_t error = 0; dctx->fseEntropy = 1; { U32 i; for (i=0; ientropy.rep[i]; } RETURN_ERROR_IF( @@ -928,17 +974,25 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, BIT_DStream_endOfBuffer < BIT_DStream_completed && BIT_DStream_completed < BIT_DStream_overflow); - for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) { - nbSeq--; - { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset); - size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); - DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); - if (ZSTD_isError(oneSeqSize)) return oneSeqSize; - op += oneSeqSize; - } } + for ( ; ; ) { + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); + size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + BIT_reloadDStream(&(seqState.DStream)); + /* gcc and clang both don't like early returns in this loop. + * gcc doesn't like early breaks either. + * Instead save an error and report it at the end. + * When there is an error, don't increment op, so we don't + * overwrite. + */ + if (UNLIKELY(ZSTD_isError(oneSeqSize))) error = oneSeqSize; + else op += oneSeqSize; + if (UNLIKELY(!--nbSeq)) break; + } /* check if reached exact end */ DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); + if (ZSTD_isError(error)) return error; RETURN_ERROR_IF(nbSeq, corruption_detected); RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected); /* save reps for next block */ @@ -965,87 +1019,7 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, } #endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ - - #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT -FORCE_INLINE_TEMPLATE seq_t -ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets) -{ - seq_t seq; - U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits; - U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits; - U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits; - U32 const totalBits = llBits+mlBits+ofBits; - U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue; - U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue; - U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue; - - /* sequence */ - { size_t offset; - if (!ofBits) - offset = 0; - else { - ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); - ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); - assert(ofBits <= MaxOff); - if (MEM_32bits() && longOffsets) { - U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1); - offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); - if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream); - if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits); - } else { - offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); - } - } - - if (ofBits <= 1) { - offset += (llBase==0); - if (offset) { - size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ - if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset = temp; - } else { - offset = seqState->prevOffset[0]; - } - } else { - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset; - } - seq.offset = offset; - } - - seq.matchLength = mlBase + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ - if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) - BIT_reloadDStream(&seqState->DStream); - if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) - BIT_reloadDStream(&seqState->DStream); - /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */ - ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); - - seq.litLength = llBase + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); - - { size_t const pos = seqState->pos + seq.litLength; - const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart; - seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. - * No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */ - seqState->pos = pos + seq.matchLength; - } - - /* ANS state update */ - ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ - ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ - - return seq; -} - FORCE_INLINE_TEMPLATE size_t ZSTD_decompressSequencesLong_body( ZSTD_DCtx* dctx, @@ -1088,14 +1062,14 @@ ZSTD_decompressSequencesLong_body( /* prepare in advance */ for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb Date: Tue, 26 Nov 2019 10:24:09 -0800 Subject: [PATCH 104/402] travis : added test durations as a guide when doing test selection --- .travis.yml | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index ec1adab0302..018596044b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,39 +26,39 @@ env: matrix: fast_finish: true include: - - name: arm64 + - name: arm64 # ~2.5 mn os: linux arch: arm64 script: - make check - - name: make test (complete) + - name: make test (complete) # ~14mn script: # DEVNULLRIGHTS : will request sudo rights to test permissions on /dev/null - DEVNULLRIGHTS=test make test - - name: gcc-6 + gcc-7 compilation + - name: gcc-6 + gcc-7 compilation # ~ 3mn script: - make gcc6install gcc7install - CC=gcc-6 CFLAGS=-Werror make -j all - make clean - CC=gcc-7 CFLAGS=-Werror make -j all - - name: gcc-8 + ASan + UBSan + Test Zstd + - name: gcc-8 + ASan + UBSan + Test Zstd # ~6.5mn script: - make gcc8install - CC=gcc-8 CFLAGS="-Werror" make -j all - make clean - CC=gcc-8 make -j uasan-test-zstd Date: Tue, 26 Nov 2019 10:28:21 -0800 Subject: [PATCH 105/402] moved meson and versions compatibility tests to master/cron also : joined c99 compatibility tests with gnu90 and c++ ones --- .travis.yml | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 018596044b5..0b16f9dd1bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,7 +81,7 @@ matrix: - make clean - make -j check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - - name: cmake test # ~2mn + - name: cmake build check # ~2mn script: - make cmakebuild @@ -122,7 +122,7 @@ matrix: - make arminstall - make armfuzz - - name: Xenial (AARCH64 + Fuzz Test) # ~14mn + - name: aarch64 + Fuzz Test (on Xenial) # ~14mn dist: xenial script: - make arminstall @@ -133,10 +133,6 @@ matrix: - make ppcinstall - make ppcfuzz - - name: Versions Compatibility Test # 11.5mn - script: - - make -C tests versionsTest - # check release number (release only) - name: Tag-Specific Test if: tag =~ ^v[0-9]\.[0-9] @@ -146,11 +142,15 @@ matrix: # tests for master branch and cron job only - name: OS-X # ~13mn - if: branch = master os: osx script: - make test + - name: Versions Compatibility Test # 11.5mn + if: branch = master + script: + - make -C tests versionsTest + - name: thread sanitizer # ~29mn if: branch = master script: @@ -158,20 +158,16 @@ matrix: - CC=clang-3.8 make tsan-test-zstream - CC=clang-3.8 make tsan-fuzztest - - name: C++ and gnu90 compatibility # ~2.5mn + - name: C++, gnu90 and c99 compatibility # ~3mn if: branch = master script: - make cxxtest - make clean - make gnu90build - make clean - - make travis-install # just ensures `make install` works - - - name: c99 compatibility # ~1.5mn - if: branch = master - script: - make c99build - - make -C tests test-zstd + - make clean + - make travis-install # just ensures `make install` works - name: PPC64 # ~13mn if: branch = master From 87ae7b940b817add132f5349d2006263d96378fd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 10:30:11 -0800 Subject: [PATCH 106/402] travisCI: moved compatibility tests to `dev` they are fast enough, and we want to catch such incompatibility early --- .travis.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0b16f9dd1bb..27479517bca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -110,6 +110,16 @@ matrix: - make clean - make -j msanregressiontest + - name: C++, gnu90 and c99 compatibility # ~3mn + script: + - make cxxtest + - make clean + - make gnu90build + - make clean + - make c99build + - make clean + - make travis-install # just ensures `make install` works + - name: Valgrind + Fuzz Test Stack Mode # ~ 7mn script: - make valgrindinstall @@ -122,7 +132,7 @@ matrix: - make arminstall - make armfuzz - - name: aarch64 + Fuzz Test (on Xenial) # ~14mn + - name: Qemu aarch64 + Fuzz Test (on Xenial) # ~14mn dist: xenial script: - make arminstall @@ -158,17 +168,6 @@ matrix: - CC=clang-3.8 make tsan-test-zstream - CC=clang-3.8 make tsan-fuzztest - - name: C++, gnu90 and c99 compatibility # ~3mn - if: branch = master - script: - - make cxxtest - - make clean - - make gnu90build - - make clean - - make c99build - - make clean - - make travis-install # just ensures `make install` works - - name: PPC64 # ~13mn if: branch = master script: From d4e17d0776f4cb05e9b8d044186dd6f0a541c077 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 26 Nov 2019 12:17:43 -0800 Subject: [PATCH 107/402] Negating bool, updating bool on inner branches --- lib/compress/zstd_compress.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 9211190e499..502b6b33da7 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2457,7 +2457,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, const void* src, size_t srcSize, U32 lastBlock) { size_t cSize = 0; - int usingNoCompressSuperBlock = 0; + int compressSuperBlock = 1; DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); @@ -2473,7 +2473,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, */ if (cSize == 0) { cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); - usingNoCompressSuperBlock = 1; + compressSuperBlock = 0; /* In compression, there is an assumption that a compressed block is always * within the size of ZSTD_compressBound(). However, SuperBlock compression * can exceed the limit due to overhead of headers from SubBlocks. @@ -2491,6 +2491,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, * compress normally. */ + compressSuperBlock = 1; cSize = ZSTD_compressSequences(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, @@ -2501,6 +2502,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, FORWARD_IF_ERROR(cSize); if (cSize == 0) { + compressSuperBlock = 0; /* If compressSequences didn't work, we just output a regular * uncompressed block */ cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); @@ -2513,7 +2515,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, } } - if (!ZSTD_isError(cSize) && !usingNoCompressSuperBlock) { + if (!ZSTD_isError(cSize) && compressSuperBlock) { /* confirm repcodes and entropy tables when emitting a compressed block */ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; zc->blockState.prevCBlock = zc->blockState.nextCBlock; From a3a3c62b81ef41fc3edbc991c165ff0acd3a29be Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 26 Nov 2019 12:24:19 -0800 Subject: [PATCH 108/402] [fuzz] Only set HUF_repeat_valid if loaded table has all non-zero weights (#1898) Fixes a fuzz issue where dictionary_round_trip failed because the compressor was generating corrupt files thanks to zero weights in the table. * Only setting loaded dict huf table to valid on non-zero * Adding hasNoZeroWeights test to fse tables * Forbiding nbBits != 0 when weight == 0 * Reverting the last commit * Setting table log to 0 when weight == 0 * Small (invalid) zero weight dict test * Small (valid) zero weight dict test * Initializing repeatMode vars to check before zero check * Removing FSE changes to seperate pr * Reverting accidentally changed file * Negating bool, using unsigned, optimization nit --- lib/common/huf.h | 2 +- lib/compress/huf_compress.c | 6 ++++-- lib/compress/zstd_compress.c | 14 +++++++++++--- tests/dict-files/zero-weight-dict | Bin 0 -> 153 bytes tests/playTests.sh | 17 ++++++++++++++++- 5 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 tests/dict-files/zero-weight-dict diff --git a/lib/common/huf.h b/lib/common/huf.h index 3026c43ea03..4a87db5c162 100644 --- a/lib/common/huf.h +++ b/lib/common/huf.h @@ -247,7 +247,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, /** HUF_readCTable() : * Loading a CTable saved with HUF_writeCTable() */ -size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); /** HUF_getNbBits() : * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 0cbba2c994e..b8e6fb38676 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -169,7 +169,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize, } -size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights) { BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */ U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ @@ -192,9 +192,11 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void } } /* fill nbBits */ + *hasZeroWeights = 0; { U32 n; for (n=0; nentropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr); + unsigned hasZeroWeights; + size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, + dictEnd-dictPtr, &hasZeroWeights); + + /* We only set the loaded table as valid if it contains all non-zero + * weights. Otherwise, we set it to check */ + if (!hasZeroWeights) + bs->entropy.huf.repeatMode = HUF_repeat_valid; + else bs->entropy.huf.repeatMode = HUF_repeat_check; + RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted); RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted); dictPtr += hufHeaderSize; @@ -2967,7 +2976,6 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted); } } - bs->entropy.huf.repeatMode = HUF_repeat_valid; bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; diff --git a/tests/dict-files/zero-weight-dict b/tests/dict-files/zero-weight-dict new file mode 100644 index 0000000000000000000000000000000000000000..c40412052137bc1963005832261c0d7bba3cf2bc GIT binary patch literal 153 zcmXqCV({j_!hZ%c0cl1?y}iLNME7hsam>Tyr|cHr`<`*TmPqDB));7UIf*WrRDV@X zQ10Nn8|O49L4XnKWhMn4F7~6%ix?a2cC)f599p@cPwmRn$VrDaxD-=*3|j;g7#JKF o98z2ufIy^RZLkQC_EBu zstd zero weight dict test " +rm -f tmp* +cp "$TESTDIR/dict-files/zero-weight-dict" tmp_input +$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input +$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp +$DIFF tmp_decomp tmp_input +rm -rf tmp* + +println "\n===> zstd (valid) zero weight dict test " +rm -f tmp* +# 0 has a non-zero weight in the dictionary +echo "0000000000000000000000000" > tmp_input +$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input +$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp +$DIFF tmp_decomp tmp_input +rm -rf tmp* println "\n===> size-hint mode" @@ -1189,7 +1205,6 @@ $ZSTD --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c test -f dictionary rm -f tmp* dictionary - if [ "$isWindows" = false ] ; then println "\n===> zstd fifo named pipe test " From 49cacd858bc99ebed57a1c408119eba02700fe51 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 14:18:09 -0800 Subject: [PATCH 109/402] fixed fifo test --- tests/playTests.sh | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index 38582f079fe..d306a41c223 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -114,6 +114,7 @@ else fi + println "\n===> simple tests " ./datagen > tmp @@ -335,8 +336,20 @@ $ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!" rm tmp* -if [ -n "$DEVNULLRIGHTS" ] -then +if [ "$isWindows" = false ] ; then + println "\n===> zstd fifo named pipe test " + echo "Hello World!" > tmp_original + mkfifo tmp_named_pipe + # note : fifo test doesn't work in combination with `dd` or `cat` + echo "Hello World!" > tmp_named_pipe & + $ZSTD tmp_named_pipe -o tmp_compressed + $ZSTD -d -o tmp_decompressed tmp_compressed + $DIFF -s tmp_original tmp_decompressed + rm -rf tmp* +fi + + +if [ -n "$DEVNULLRIGHTS" ] ; then # these tests requires sudo rights, which is uncommon. # they are only triggered if DEVNULLRIGHTS macro is defined. println "\n===> checking /dev/null permissions are unaltered " @@ -1259,18 +1272,4 @@ test -f dictionary rm -f tmp* dictionary -if [ "$isWindows" = false ] ; then - -println "\n===> zstd fifo named pipe test " -dd bs=1 count=10 if=/dev/zero of=tmp_original -mkfifo named_pipe -dd bs=1 count=10 if=/dev/zero of=named_pipe & -$ZSTD named_pipe -o tmp_compressed -$ZSTD -d -o tmp_decompressed tmp_compressed -$DIFF -s tmp_original tmp_decompressed -rm -rf tmp* -rm -rf named_pipe - -fi - rm -f tmp* From f622c0adf36683acba6ae02406ad0694515336f0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 14:48:23 -0800 Subject: [PATCH 110/402] switched UTIL_refFilename() to an assert() --- programs/util.c | 2 +- programs/util.h | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/programs/util.c b/programs/util.c index bb511bd5d5b..3c541c55040 100644 --- a/programs/util.c +++ b/programs/util.c @@ -372,7 +372,7 @@ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize) void UTIL_refFilename(FileNamesTable* fnt, const char* filename) { - if (fnt->tableCapacity <= fnt->tableSize) abort(); + assert(fnt->tableSize < fnt->tableCapacity); fnt->fileNames[fnt->tableSize] = filename; fnt->tableSize++; } diff --git a/programs/util.h b/programs/util.h index 0065ec46f72..42978b958c2 100644 --- a/programs/util.h +++ b/programs/util.h @@ -221,11 +221,10 @@ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize); /*! UTIL_refFilename() : - * Add a read-only name to reference into @fnt table. - * Since @filename is only referenced, its lifetime must outlive @fnt. - * This function never fails, but it can abort(). - * Internal table must be large enough to reference a new member - * (capacity > size), otherwise the function will abort(). + * Add a reference to read-only name into @fnt table. + * As @filename is only referenced, its lifetime must outlive @fnt. + * Internal table must be large enough to reference a new member, + * otherwise its UB (protected by an `assert()`). */ void UTIL_refFilename(FileNamesTable* fnt, const char* filename); From 2d9fad4f529afe48f36d61b29dd040e6d411ae96 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 14:53:37 -0800 Subject: [PATCH 111/402] fixed minor VS warning, on parameter difference complaining about a `const` property on one side but not the other. --- programs/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.h b/programs/util.h index 42978b958c2..27f5d5a0b77 100644 --- a/programs/util.h +++ b/programs/util.h @@ -131,7 +131,7 @@ int UTIL_isFIFO(const char* infilename); #define UTIL_FILESIZE_UNKNOWN ((U64)(-1)) U64 UTIL_getFileSize(const char* infilename); -U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles); +U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles); int UTIL_getFileStat(const char* infilename, stat_t* statbuf); int UTIL_setFileStat(const char* filename, stat_t* statbuf); int UTIL_chmod(char const* filename, mode_t permissions); /*< like chmod, but avoid changing permission of /dev/null */ From f57be339ab78c0a23b75eba23bbd4f4b553341e7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 15:01:16 -0800 Subject: [PATCH 112/402] travisCI : removed `trusty` generic statement trusty is out of long term support. let's run (most) tests on "current" platform. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 27479517bca..524d183f571 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ # Medium Tests: Run on all commits/PRs to dev branch language: c -dist: trusty git: depth: 1 From a684b82774556f3546123230ccdb95d528c41012 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 15:16:53 -0800 Subject: [PATCH 113/402] util: isolated some dependencies from *.h to *.c so that they don't get transitively included into users of util.h. --- programs/util.c | 15 +++++++++++++++ programs/util.h | 16 +--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/programs/util.c b/programs/util.c index 3c541c55040..5354e864d7b 100644 --- a/programs/util.c +++ b/programs/util.c @@ -17,9 +17,24 @@ extern "C" { * Dependencies ******************************************/ #include "util.h" /* note : ensure that platform.h is included first ! */ +#include /* malloc, realloc, free */ +#include /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */ #include #include +#if defined(_WIN32) +# include /* utime */ +# include /* _chmod */ +#else +# include /* chown, stat */ +# if PLATFORM_POSIX_VERSION < 200809L +# include /* utime */ +# else +# include /* AT_FDCWD */ +# include /* utimensat */ +# endif +#endif + #if defined(_MSC_VER) || defined(__MINGW32__) || defined (__MSVCRT__) #include /* needed for _mkdir in windows */ #endif diff --git a/programs/util.h b/programs/util.h index 27f5d5a0b77..53431657d1e 100644 --- a/programs/util.h +++ b/programs/util.h @@ -20,25 +20,11 @@ extern "C" { * Dependencies ******************************************/ #include "platform.h" /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */ -#include /* malloc, realloc, free */ #include /* size_t, ptrdiff_t */ #include /* fprintf */ #include /* stat, utime */ #include /* stat, chmod */ -#if defined(_WIN32) -# include /* utime */ -# include /* _chmod */ -#else -# include /* chown, stat */ -# if PLATFORM_POSIX_VERSION < 200809L -# include /* utime */ -# else -# include /* AT_FDCWD */ -# include /* utimensat */ -# endif -#endif -#include /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */ -#include "mem.h" /* U32, U64 */ +#include "mem.h" /* U64 */ /*-************************************************************ * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW From 7543cd055cb94a26f03aff44e334b3c4cba009fe Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 15:21:58 -0800 Subject: [PATCH 114/402] moved UTIL_DISPLAY() inside util.c --- programs/util.c | 14 ++++++++++---- programs/util.h | 2 -- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/programs/util.c b/programs/util.c index 5354e864d7b..703c06552bd 100644 --- a/programs/util.c +++ b/programs/util.c @@ -49,8 +49,11 @@ extern "C" { * Internal Macros ******************************************/ -/* CONTROL is like an assert(), but is never disabled. - * Since it's always active, it can trigger side effects. +/* CONTROL is almost like an assert(), but is never disabled. + * It's designed for failures that may happen rarely, + * but we don't want to maintain a specific error code path for them, + * such as a malloc() returning NULL for example. + * Since it's always active, this macro can trigger side effects. */ #define CONTROL(c) { \ if (!(c)) { \ @@ -59,8 +62,11 @@ extern "C" { exit(1); \ } } -/* - * A modified version of realloc(). +/* console log */ +#define UTIL_DISPLAY(...) fprintf(stderr, __VA_ARGS__) +#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } } + +/* A modified version of realloc(). * If UTIL_realloc() fails the original block is freed. */ UTIL_STATIC void* UTIL_realloc(void *ptr, size_t size) diff --git a/programs/util.h b/programs/util.h index 53431657d1e..7beaec64e81 100644 --- a/programs/util.h +++ b/programs/util.h @@ -92,8 +92,6 @@ extern "C" { * Console log ******************************************/ extern int g_utilDisplayLevel; -#define UTIL_DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } } /*-**************************************** From aaab618ae9e02fa3f7ac539c304419f7b2e1acbd Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 15:25:32 -0800 Subject: [PATCH 115/402] pushed aside stdio.h too since only UTIL_DISPLAY() depended on it. --- programs/util.c | 1 + programs/util.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 703c06552bd..5e7a10c1232 100644 --- a/programs/util.c +++ b/programs/util.c @@ -18,6 +18,7 @@ extern "C" { ******************************************/ #include "util.h" /* note : ensure that platform.h is included first ! */ #include /* malloc, realloc, free */ +#include /* fprintf */ #include /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */ #include #include diff --git a/programs/util.h b/programs/util.h index 7beaec64e81..6e8711fd152 100644 --- a/programs/util.h +++ b/programs/util.h @@ -21,7 +21,6 @@ extern "C" { ******************************************/ #include "platform.h" /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */ #include /* size_t, ptrdiff_t */ -#include /* fprintf */ #include /* stat, utime */ #include /* stat, chmod */ #include "mem.h" /* U64 */ From 96ee20758cb1b76edd46b27d4ea38b516fe15f63 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 15:44:33 -0800 Subject: [PATCH 116/402] assembleFNT() can no longer fail --- programs/util.c | 15 +++++++------- programs/util.h | 55 ++++++++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/programs/util.c b/programs/util.c index 5e7a10c1232..e4c2fbf2d35 100644 --- a/programs/util.c +++ b/programs/util.c @@ -366,7 +366,7 @@ FileNamesTable* UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf) { FileNamesTable* const table = (FileNamesTable*) malloc(sizeof(*table)); - if(!table) return NULL; + CONTROL(table != NULL); table->fileNames = filenames; table->buf = buf; table->tableSize = tableSize; @@ -579,7 +579,7 @@ static int UTIL_prepareFileList(const char *dirName, } if (errno != 0) { - UTIL_DISPLAYLEVEL(1, "readdir(%s) error: %s\n", dirName, strerror(errno)); + UTIL_DISPLAYLEVEL(1, "readdir(%s) error: %s \n", dirName, strerror(errno)); free(*bufStart); *bufStart = NULL; } @@ -594,7 +594,7 @@ static int UTIL_prepareFileList(const char *dirName, char** bufEnd, int followLinks) { (void)bufStart; (void)bufEnd; (void)pos; (void)followLinks; - UTIL_DISPLAYLEVEL(1, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName); + UTIL_DISPLAYLEVEL(1, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE) \n", dirName); return 0; } @@ -665,7 +665,8 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) pos += strlen(fileNamesTable[ifnNb]) + 1; } { FileNamesTable* const fnt = UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); -#ifdef __clang_analyzer__ +#if 0 && defined(__clang_analyzer__) + /* note : this trick might not be necessary anymore */ /* scan-build does not understand ownership transfer. * In _some_ versions, it believes that there is a leak of @buf and @fileNamesTable * on leaving the function, which is not the case, @@ -761,8 +762,7 @@ int UTIL_countPhysicalCores(void) } } else { done = TRUE; - } - } + } } ptr = buffer; @@ -874,8 +874,7 @@ int UTIL_countPhysicalCores(void) } else if (ferror(cpuinfo)) { /* fall back on the sysconf value */ goto failed; - } - } + } } if (siblings && cpu_cores) { ratio = siblings / cpu_cores; } diff --git a/programs/util.h b/programs/util.h index 6e8711fd152..95cc9c6044a 100644 --- a/programs/util.h +++ b/programs/util.h @@ -25,17 +25,18 @@ extern "C" { #include /* stat, chmod */ #include "mem.h" /* U64 */ + /*-************************************************************ * Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW ***************************************************************/ #if defined(_MSC_VER) && (_MSC_VER >= 1400) -# define UTIL_fseek _fseeki64 +# define UTIL_fseek _fseeki64 #elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ # define UTIL_fseek fseeko #elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) -# define UTIL_fseek fseeko64 +# define UTIL_fseek fseeko64 #else -# define UTIL_fseek fseek +# define UTIL_fseek fseek #endif @@ -126,17 +127,8 @@ const char* UTIL_getFileExtension(const char* infilename); * Lists of Filenames ******************************************/ -#ifdef _WIN32 -# define UTIL_HAS_CREATEFILELIST -#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */ -# define UTIL_HAS_CREATEFILELIST -#else - /* do not define UTIL_HAS_CREATEFILELIST */ -#endif /* #ifdef _WIN32 */ - typedef struct -{ - const char** fileNames; +{ const char** fileNames; char* buf; /* fileNames are stored in this buffer (or are read-only) */ size_t tableSize; /* nb of fileNames */ size_t tableCapacity; @@ -153,7 +145,9 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName); /*! UTIL_assembleFileNamesTable() : * This function takes ownership of its arguments, @filenames and @buf, * and store them inside the created object. - * @return : FileNamesTable*, or NULL, if allocation fails. + * note : this function never fails, + * it will rather exit() the program if internal allocation fails. + * @return : resulting FileNamesTable* object. */ FileNamesTable* UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf); @@ -185,15 +179,8 @@ void UTIL_expandFNT(FileNamesTable** fnt, int followLinks); * @return : a FileNamesTable* object, * or NULL in case of error */ -FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames); - -/*! UTIL_createExpandedFNT() : - * read names from @filenames, and expand those corresponding to directories - * @return : an expanded FileNamesTable*, where each name is a file - * or NULL in case of error - */ -FileNamesTable* UTIL_createExpandedFNT(const char** filenames, size_t nbFilenames, int followLinks); - +FileNamesTable* +UTIL_createFNT_fromROTable(const char** filenames, size_t nbFilenames); /*! UTIL_allocateFileNamesTable() : * Allocates a table of const char*, to insert read-only names later on. @@ -212,6 +199,28 @@ FileNamesTable* UTIL_allocateFileNamesTable(size_t tableSize); void UTIL_refFilename(FileNamesTable* fnt, const char* filename); +/* UTIL_createExpandedFNT() is only active if UTIL_HAS_CREATEFILELIST is defined. + * Otherwise, UTIL_createExpandedFNT() is a shell function which does nothing + * apart from displaying a warning message. + */ +#ifdef _WIN32 +# define UTIL_HAS_CREATEFILELIST +#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */ +# define UTIL_HAS_CREATEFILELIST +#else + /* do not define UTIL_HAS_CREATEFILELIST */ +#endif + +/*! UTIL_createExpandedFNT() : + * read names from @filenames, and expand those corresponding to directories. + * links are followed or not depending on @followLinks directive. + * @return : an expanded FileNamesTable*, where each name is a file + * or NULL in case of error + */ +FileNamesTable* +UTIL_createExpandedFNT(const char** filenames, size_t nbFilenames, int followLinks); + + /*-**************************************** * System ******************************************/ From ecaf3ce1031f54bc1a8605e75d7fc7f20d4f6dc5 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 16:44:56 -0800 Subject: [PATCH 117/402] reverted ppc qemu and scanbuild on trusty ppc cross-compilation seems broken outside of trusty scan-build version changes with distrib version, resulting in a different list of false positives --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 524d183f571..fd486af6926 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,6 +85,7 @@ matrix: - make cmakebuild - name: static analyzer scanbuild # ~26mn + dist: trusty # note : it's important to pin down a version of static analyzer, since newer versions find different false positives script: - make staticAnalyze @@ -137,7 +138,8 @@ matrix: - make arminstall - make aarch64fuzz - - name: PPC + Fuzz Test # ~13mn + - name: Qemu PPC + Fuzz Test # ~13mn + dist: trusty # it seems ppc cross-compilation fails on "current" script: - make ppcinstall - make ppcfuzz From d5b4a7ea58be15ef3a8c0ebde9918a4393d45ac2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 26 Nov 2019 17:46:57 -0800 Subject: [PATCH 118/402] removed scanbuild workaround --- programs/util.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/programs/util.c b/programs/util.c index e4c2fbf2d35..41ac1379af2 100644 --- a/programs/util.c +++ b/programs/util.c @@ -625,14 +625,13 @@ const char* UTIL_getFileExtension(const char* infilename) FileNamesTable* UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) { - size_t pos; unsigned nbFiles; char* buf = (char*)malloc(LIST_SIZE_INCREASE); char* bufend = buf + LIST_SIZE_INCREASE; if (!buf) return NULL; - { size_t ifnNb; + { size_t ifnNb, pos; for (ifnNb=0, pos=0, nbFiles=0; ifnNb= 0); buf = (char*)UTIL_realloc(buf, (size_t)newListSize); - bufend = buf + newListSize; if (!buf) return NULL; + bufend = buf + newListSize; } if (buf + pos + len < bufend) { memcpy(buf+pos, inputNames[ifnNb], len+1); /* including final \0 */ @@ -655,7 +654,7 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) if (nbFiles == 0) { free(buf); return NULL; } - { size_t ifnNb; + { size_t ifnNb, pos; const char** const fileNamesTable = (const char**)malloc((nbFiles + 1) * sizeof(*fileNamesTable)); if (!fileNamesTable) { free(buf); return NULL; } @@ -664,20 +663,7 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) if (buf + pos > bufend) { free(buf); free((void*)fileNamesTable); return NULL; } pos += strlen(fileNamesTable[ifnNb]) + 1; } - { FileNamesTable* const fnt = UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); -#if 0 && defined(__clang_analyzer__) - /* note : this trick might not be necessary anymore */ - /* scan-build does not understand ownership transfer. - * In _some_ versions, it believes that there is a leak of @buf and @fileNamesTable - * on leaving the function, which is not the case, - * as they are referenced inside the object created by UTIL_assembleFileNamesTable(). - * In order to silence this false warning, let's "pretend" that these memory objects are freed. - * This directive is only read by scan-build, due to __clang_analyzer__ macros */ - free(buf); - free(fileNamesTable); -#endif - return fnt; - } + return UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); } } @@ -695,18 +681,7 @@ FileNamesTable* UTIL_createFNT_fromROTable(const char** filenames, size_t nbFile const char** const newFNTable = (const char**)malloc(sizeof_FNTable); if (newFNTable==NULL) return NULL; memcpy((void*)newFNTable, filenames, sizeof_FNTable); /* void* : mitigate a Visual compiler bug or limitation */ - { FileNamesTable* const fnt = UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL);; -#ifdef __clang_analyzer__ - /* scan-build does not understand ownership transfer. - * In _some_ versions, it believes that there is a leak of @newFNTable - * on leaving the function, which is not the case, - * as they are referenced inside the object created by UTIL_assembleFileNamesTable(). - * In order to silence this false warning, let's "pretend" that these memory objects are freed. - * This directive is only read by scan-build, due to __clang_analyzer__ macros */ - free(newFNTable); -#endif - return fnt; - } + return UTIL_assembleFileNamesTable(newFNTable, nbFilenames, NULL); } From 8eb499d3541579ab0a9cad8fc454259b3688999b Mon Sep 17 00:00:00 2001 From: Peter Lesslie Date: Tue, 26 Nov 2019 19:36:33 -0600 Subject: [PATCH 119/402] Check for fread failure On failure fread may return either a short read or 0. Need to use ferror to detect error versus eof. --- programs/fileio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index a45dedc464f..8fc25d357d5 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1769,7 +1769,7 @@ static int FIO_passThrough(const FIO_prefs_t* const prefs, size_t alreadyLoaded) { size_t const blockSize = MIN(64 KB, bufferSize); - size_t readFromInput = 1; + size_t readFromInput; unsigned storedSkips = 0; /* assumption : ress->srcBufferLoaded bytes already loaded and stored within buffer */ @@ -1779,10 +1779,15 @@ static int FIO_passThrough(const FIO_prefs_t* const prefs, return 1; } } - while (readFromInput) { + do { readFromInput = fread(buffer, 1, blockSize, finput); storedSkips = FIO_fwriteSparse(prefs, foutput, buffer, readFromInput, storedSkips); + } while (readFromInput == blockSize); + if (ferror(finput)) { + DISPLAYLEVEL(1, "Pass-through read error : %s\n", strerror(errno)); + return 1; } + assert(feof(finput)); FIO_fwriteSparseEnd(prefs, foutput, storedSkips); return 0; From d6e32afa0ab24aee51c3989528281adc4ffad266 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 27 Nov 2019 12:44:02 -0800 Subject: [PATCH 120/402] added mingw cross compilation tests based on a script in RocksDB project. also : pushed qemu aarch64 tests to master/cron, since there are already hardware aarch64 tests on dev. --- .travis.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index fd486af6926..c7d027f997a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,7 +85,7 @@ matrix: - make cmakebuild - name: static analyzer scanbuild # ~26mn - dist: trusty # note : it's important to pin down a version of static analyzer, since newer versions find different false positives + dist: trusty # note : it's important to pin down a version of static analyzer, since newer versions find different false positives script: - make staticAnalyze @@ -120,6 +120,11 @@ matrix: - make clean - make travis-install # just ensures `make install` works + - name: mingw cross-compilation + script : + - sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix; + - CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ make + - name: Valgrind + Fuzz Test Stack Mode # ~ 7mn script: - make valgrindinstall @@ -132,12 +137,6 @@ matrix: - make arminstall - make armfuzz - - name: Qemu aarch64 + Fuzz Test (on Xenial) # ~14mn - dist: xenial - script: - - make arminstall - - make aarch64fuzz - - name: Qemu PPC + Fuzz Test # ~13mn dist: trusty # it seems ppc cross-compilation fails on "current" script: @@ -175,6 +174,14 @@ matrix: - make ppcinstall - make ppc64fuzz + # note : we already have aarch64 tests on hardware + - name: Qemu aarch64 + Fuzz Test (on Xenial) # ~14mn + if: branch = master + dist: xenial + script: + - make arminstall + - make aarch64fuzz + - name: zlib wrapper test # ~7.5mn if: branch = master script: From 52dc6ff00eb653091d4ee01c8f445325a2ece09c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 27 Nov 2019 14:39:43 -0800 Subject: [PATCH 121/402] travis: updated mingw cross compilation test - only compiles zstd CLI - enforces zero warning tolerance policy note : mingw compilation of the library complains (warning) about -fPIC flag. It mostly ignores it, so it's not a big issue. Still, it would need to be fixed if library cross-compilation becomes part of CI. At this stage, it's unclear if this is a scenario. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7d027f997a..57242a488ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,7 +85,7 @@ matrix: - make cmakebuild - name: static analyzer scanbuild # ~26mn - dist: trusty # note : it's important to pin down a version of static analyzer, since newer versions find different false positives + dist: trusty # note : it's important to pin down a version of static analyzer, since different versions report different false positives script: - make staticAnalyze @@ -123,7 +123,7 @@ matrix: - name: mingw cross-compilation script : - sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix; - - CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ make + - CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CFLAGS="-Werror -O1" make zstd - name: Valgrind + Fuzz Test Stack Mode # ~ 7mn script: From a49417b5af0cf5669e6a97c0a24028db53276b2d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 2 Dec 2019 14:28:18 -0800 Subject: [PATCH 122/402] fix recent issue combining -r with empty list of input files This would resize the table of input filenames to zero, delivering an empty table, to which it was no longer possible to add stdin. --- programs/util.c | 20 ++++++++++++++------ programs/zstdcli.c | 28 ++++++++++++++++------------ tests/playTests.sh | 16 +++++++++++----- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/programs/util.c b/programs/util.c index 41ac1379af2..0fc95512ea2 100644 --- a/programs/util.c +++ b/programs/util.c @@ -362,18 +362,24 @@ UTIL_createFileNamesTable_fromFileName(const char* inputFileName) } } -FileNamesTable* -UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf) +static FileNamesTable* +UTIL_assembleFileNamesTable2(const char** filenames, size_t tableSize, size_t tableCapacity, char* buf) { FileNamesTable* const table = (FileNamesTable*) malloc(sizeof(*table)); CONTROL(table != NULL); table->fileNames = filenames; table->buf = buf; table->tableSize = tableSize; - table->tableCapacity = tableSize; + table->tableCapacity = tableCapacity; return table; } +FileNamesTable* +UTIL_assembleFileNamesTable(const char** filenames, size_t tableSize, char* buf) +{ + return UTIL_assembleFileNamesTable2(filenames, tableSize, tableSize, buf); +} + void UTIL_freeFileNamesTable(FileNamesTable* table) { if (table==NULL) return; @@ -652,10 +658,11 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) if (buf == NULL) return NULL; } } } - if (nbFiles == 0) { free(buf); return NULL; } + /* note : even if nbFiles==0, function returns a valid, though empty, FileNamesTable* object */ { size_t ifnNb, pos; - const char** const fileNamesTable = (const char**)malloc((nbFiles + 1) * sizeof(*fileNamesTable)); + size_t const fntCapacity = nbFiles + 1; /* minimum 1, allows adding one reference, typically stdin */ + const char** const fileNamesTable = (const char**)malloc(fntCapacity * sizeof(*fileNamesTable)); if (!fileNamesTable) { free(buf); return NULL; } for (ifnNb = 0, pos = 0; ifnNb < nbFiles; ifnNb++) { @@ -663,7 +670,7 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) if (buf + pos > bufend) { free(buf); free((void*)fileNamesTable); return NULL; } pos += strlen(fileNamesTable[ifnNb]) + 1; } - return UTIL_assembleFileNamesTable(fileNamesTable, nbFiles, buf); + return UTIL_assembleFileNamesTable2(fileNamesTable, nbFiles, fntCapacity, buf); } } @@ -671,6 +678,7 @@ UTIL_createExpandedFNT(const char** inputNames, size_t nbIfns, int followLinks) void UTIL_expandFNT(FileNamesTable** fnt, int followLinks) { FileNamesTable* const newFNT = UTIL_createExpandedFNT((*fnt)->fileNames, (*fnt)->tableSize, followLinks); + CONTROL(newFNT != NULL); UTIL_freeFileNamesTable(*fnt); *fnt = newFNT; } diff --git a/programs/zstdcli.c b/programs/zstdcli.c index cf2f3682d1d..15fcd8a5390 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -27,10 +27,12 @@ **************************************/ #include "platform.h" /* IS_CONSOLE, PLATFORM_POSIX_VERSION */ #include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */ -#include /* fprintf(), stdin, stdout, stderr */ #include /* getenv */ #include /* strcmp, strlen */ +#include /* fprintf(), stdin, stdout, stderr */ #include /* errno */ +#include /* assert */ + #include "fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ #ifndef ZSTD_NOBENCH # include "benchzstd.h" /* BMK_benchFiles */ @@ -508,11 +510,13 @@ static void printVersion(void) /* Environment variables for parameter setting */ #define ENV_CLEVEL "ZSTD_CLEVEL" -/* functions that pick up environment variables */ +/* pick up environment variables + * requirement : g_displayOut must be set */ static int init_cLevel(void) { const char* const env = getenv(ENV_CLEVEL); - if (env) { - const char *ptr = env; + assert(g_displayOut == stderr); /* to print error messages */ + if (env != NULL) { + const char* ptr = env; int sign = 1; if (*ptr == '-') { sign = -1; @@ -524,14 +528,13 @@ static int init_cLevel(void) { if ((*ptr>='0') && (*ptr<='9')) { unsigned absLevel; if (readU32FromCharChecked(&ptr, &absLevel)) { - DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large\n", ENV_CLEVEL, env); + DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: numeric value too large \n", ENV_CLEVEL, env); return ZSTDCLI_CLEVEL_DEFAULT; } else if (*ptr == 0) { return sign * (int)absLevel; - } - } + } } - DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid integer value\n", ENV_CLEVEL, env); + DISPLAYLEVEL(2, "Ignore environment variable setting %s=%s: not a valid integer value \n", ENV_CLEVEL, env); } return ZSTDCLI_CLEVEL_DEFAULT; @@ -543,14 +546,14 @@ typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom #ifdef ZSTD_NOCOMPRESS /* symbols from compression library are not defined and should not be invoked */ -# define MINCLEVEL -50 +# define MINCLEVEL -99 # define MAXCLEVEL 22 #else # define MINCLEVEL ZSTD_minCLevel() # define MAXCLEVEL ZSTD_maxCLevel() #endif -int main(int argCount, const char* argv[]) +int main(int const argCount, const char* argv[]) { int argNb, followLinks = 0, @@ -582,7 +585,7 @@ int main(int argCount, const char* argv[]) zstd_operation_mode operation = zom_compress; ZSTD_compressionParameters compressionParams; int cLevel; - int cLevelLast = -1000000000; + int cLevelLast = MINCLEVEL - 1; /* lower than minimum */ unsigned recursive = 0; unsigned memLimit = 0; FileNamesTable* filenames = UTIL_allocateFileNamesTable((size_t)argCount); /* argCount >= 1 */ @@ -613,9 +616,10 @@ int main(int argCount, const char* argv[]) /* init */ (void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */ (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */ + assert(argCount >= 1); if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAY("zstd: allocation error \n"); exit(1); } g_displayOut = stderr; - cLevel = init_cLevel(); + cLevel = init_cLevel(); /* must be done after setting g_displayOut, since some error message might be printed */ programName = lastNameFromPath(programName); #ifdef ZSTD_MULTITHREAD nbWorkers = 1; diff --git a/tests/playTests.sh b/tests/playTests.sh index 84cb2d52d89..4886aac2ba8 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -142,7 +142,7 @@ ZSTD_CLEVEL=- $ZSTD -f tmp # malformed env var, warn and revert to default set ZSTD_CLEVEL=a $ZSTD -f tmp # malformed env var, warn and revert to default setting ZSTD_CLEVEL=+a $ZSTD -f tmp # malformed env var, warn and revert to default setting ZSTD_CLEVEL=3a7 $ZSTD -f tmp # malformed env var, warn and revert to default setting -ZSTD_CLEVEL=50000000000 $ZSTD -f tmp # numeric value too large, warn and revert to default setting +ZSTD_CLEVEL=50000000000 $ZSTD -f tmp # numeric value too large, warn and revert to default setting println "test : override ZSTD_CLEVEL with command line option" ZSTD_CLEVEL=12 $ZSTD --fast=3 -f tmp # overridden by command line option println "test : compress to stdout" @@ -239,18 +239,24 @@ if [[ $file2timestamp -ge $file1timestamp ]]; then else println "Test is not successful" fi -#File Extension check. +# File Extension check. ./datagen $size > precompressedFilterTestDir/input.zstbar $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir -#ZSTD should compress input.zstbar +# ZSTD should compress input.zstbar test -f precompressedFilterTestDir/input.zstbar.zst -#Check without the --exclude-compressed flag +# Check without the --exclude-compressed flag $ZSTD --long --rm -r precompressedFilterTestDir -#Files should get compressed again without the --exclude-compressed flag. +# Files should get compressed again without the --exclude-compressed flag. test -f precompressedFilterTestDir/input.5.zst.zst test -f precompressedFilterTestDir/input.6.zst.zst println "Test completed" + +println "\n===> recursive mode test " +# combination of -r with empty list of input file +$ZSTD -c -r < tmp > tmp.zst + + println "\n===> file removal" $ZSTD -f --rm tmp test ! -f tmp # tmp should no longer be present From 4b4de7493f3a98be960ccc21a4bd0fc6d6538f53 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 2 Dec 2019 16:08:08 -0800 Subject: [PATCH 123/402] refactoring : remove global variable g_displayOut displaying into stderr or stdout is now an explicit operation, no longer depending on some global state set elsewhere in the code. --- programs/zstdcli.c | 281 +++++++++++++++++++++++---------------------- tests/playTests.sh | 19 +-- 2 files changed, 155 insertions(+), 145 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 15fcd8a5390..b7de3d8ff18 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -94,128 +94,130 @@ typedef enum { cover, fastCover, legacy } dictType; /*-************************************ * Display Macros **************************************/ -#define DISPLAY(...) fprintf(g_displayOut, __VA_ARGS__) +#define DISPLAY_F(f, ...) fprintf((f), __VA_ARGS__) +#define DISPLAYOUT(...) DISPLAY_F(stdout, __VA_ARGS__) +#define DISPLAY(...) DISPLAY_F(stderr, __VA_ARGS__) #define DISPLAYLEVEL(l, ...) { if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } } static int g_displayLevel = DISPLAY_LEVEL_DEFAULT; /* 0 : no display, 1: errors, 2 : + result + interaction + warnings, 3 : + progression, 4 : + information */ -static FILE* g_displayOut; /*-************************************ * Command Line **************************************/ -static int usage(const char* programName) +/* print help either in `stderr` or `stdout` depending on originating request + * error (badusage) => stderr + * help (usage_advanced) => stdout + */ +static void usage(FILE* f, const char* programName) { - DISPLAY( "Usage : \n"); - DISPLAY( " %s [args] [FILE(s)] [-o file] \n", programName); - DISPLAY( "\n"); - DISPLAY( "FILE : a filename \n"); - DISPLAY( " with no FILE, or when FILE is - , read standard input\n"); - DISPLAY( "Arguments : \n"); + DISPLAY_F(f, "Usage : \n"); + DISPLAY_F(f, " %s [args] [FILE(s)] [-o file] \n", programName); + DISPLAY_F(f, "\n"); + DISPLAY_F(f, "FILE : a filename \n"); + DISPLAY_F(f, " with no FILE, or when FILE is - , read standard input\n"); + DISPLAY_F(f, "Arguments : \n"); #ifndef ZSTD_NOCOMPRESS - DISPLAY( " -# : # compression level (1-%d, default: %d) \n", ZSTDCLI_CLEVEL_MAX, ZSTDCLI_CLEVEL_DEFAULT); + DISPLAY_F(f, " -# : # compression level (1-%d, default: %d) \n", ZSTDCLI_CLEVEL_MAX, ZSTDCLI_CLEVEL_DEFAULT); #endif #ifndef ZSTD_NODECOMPRESS - DISPLAY( " -d : decompression \n"); + DISPLAY_F(f, " -d : decompression \n"); #endif - DISPLAY( " -D file: use `file` as Dictionary \n"); - DISPLAY( " -o file: result stored into `file` (only if 1 input file) \n"); - DISPLAY( " -f : overwrite output without prompting and (de)compress links \n"); - DISPLAY( "--rm : remove source file(s) after successful de/compression \n"); - DISPLAY( " -k : preserve source file(s) (default) \n"); - DISPLAY( " -h/-H : display help/long help and exit \n"); - return 0; + DISPLAY_F(f, " -D file: use `file` as Dictionary \n"); + DISPLAY_F(f, " -o file: result stored into `file` (only if 1 input file) \n"); + DISPLAY_F(f, " -f : overwrite output without prompting and (de)compress links \n"); + DISPLAY_F(f, "--rm : remove source file(s) after successful de/compression \n"); + DISPLAY_F(f, " -k : preserve source file(s) (default) \n"); + DISPLAY_F(f, " -h/-H : display help/long help and exit \n"); } -static int usage_advanced(const char* programName) +static void usage_advanced(const char* programName) { - DISPLAY(WELCOME_MESSAGE); - usage(programName); - DISPLAY( "\n"); - DISPLAY( "Advanced arguments : \n"); - DISPLAY( " -V : display Version number and exit \n"); - DISPLAY( " -v : verbose mode; specify multiple times to increase verbosity\n"); - DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n"); - DISPLAY( " -c : force write to standard output, even if it is the console\n"); - DISPLAY( " -l : print information about zstd compressed files \n"); - DISPLAY( "--exclude-compressed: only compress files that are not previously compressed \n"); + DISPLAYOUT(WELCOME_MESSAGE); + usage(stdout, programName); + DISPLAYOUT( "\n"); + DISPLAYOUT( "Advanced arguments : \n"); + DISPLAYOUT( " -V : display Version number and exit \n"); + DISPLAYOUT( " -v : verbose mode; specify multiple times to increase verbosity\n"); + DISPLAYOUT( " -q : suppress warnings; specify twice to suppress errors too\n"); + DISPLAYOUT( " -c : force write to standard output, even if it is the console\n"); + DISPLAYOUT( " -l : print information about zstd compressed files \n"); + DISPLAYOUT( "--exclude-compressed: only compress files that are not previously compressed \n"); #ifndef ZSTD_NOCOMPRESS - DISPLAY( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); - DISPLAY( "--long[=#]: enable long distance matching with given window log (default: %u)\n", g_defaultMaxWindowLog); - DISPLAY( "--fast[=#]: switch to very fast compression levels (default: %u)\n", 1); - DISPLAY( "--adapt : dynamically adapt compression level to I/O conditions \n"); - DISPLAY( "--stream-size=# : optimize compression parameters for streaming input of given number of bytes \n"); - DISPLAY( "--size-hint=# optimize compression parameters for streaming input of approximately this size\n"); - DISPLAY( "--target-compressed-block-size=# : make compressed block near targeted size \n"); -#ifdef ZSTD_MULTITHREAD - DISPLAY( " -T# : spawns # compression threads (default: 1, 0==# cores) \n"); - DISPLAY( " -B# : select size of each job (default: 0==automatic) \n"); - DISPLAY( "--rsyncable : compress using a rsync-friendly method (-B sets block size) \n"); -#endif - DISPLAY( "--no-dictID : don't write dictID into header (dictionary compression)\n"); - DISPLAY( "--[no-]check : integrity check (default: enabled) \n"); - DISPLAY( "--[no-]compress-literals : force (un)compressed literals \n"); -#endif + DISPLAYOUT( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); + DISPLAYOUT( "--long[=#]: enable long distance matching with given window log (default: %u)\n", g_defaultMaxWindowLog); + DISPLAYOUT( "--fast[=#]: switch to very fast compression levels (default: %u)\n", 1); + DISPLAYOUT( "--adapt : dynamically adapt compression level to I/O conditions \n"); + DISPLAYOUT( "--stream-size=# : optimize compression parameters for streaming input of given number of bytes \n"); + DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size\n"); + DISPLAYOUT( "--target-compressed-block-size=# : make compressed block near targeted size \n"); +# ifdef ZSTD_MULTITHREAD + DISPLAYOUT( " -T# : spawns # compression threads (default: 1, 0==# cores) \n"); + DISPLAYOUT( " -B# : select size of each job (default: 0==automatic) \n"); + DISPLAYOUT( "--rsyncable : compress using a rsync-friendly method (-B sets block size) \n"); +# endif + DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression)\n"); + DISPLAYOUT( "--[no-]check : integrity check (default: enabled) \n"); + DISPLAYOUT( "--[no-]compress-literals : force (un)compressed literals \n"); +#endif /* !ZSTD_NOCOMPRESS */ #ifdef UTIL_HAS_CREATEFILELIST - DISPLAY( " -r : operate recursively on directories \n"); - DISPLAY( "--filelist=FILE : read a list of files from FILE. \n"); - DISPLAY( "--output-dir-flat=DIR : all resulting files are stored into DIR. \n"); + DISPLAYOUT( " -r : operate recursively on directories \n"); + DISPLAYOUT( "--filelist=FILE : read a list of files from FILE. \n"); + DISPLAYOUT( "--output-dir-flat=DIR : all resulting files are stored into DIR. \n"); #endif - DISPLAY( "--format=zstd : compress files to the .zst format (default) \n"); + DISPLAYOUT( "--format=zstd : compress files to the .zst format (default) \n"); #ifdef ZSTD_GZCOMPRESS - DISPLAY( "--format=gzip : compress files to the .gz format \n"); + DISPLAYOUT( "--format=gzip : compress files to the .gz format \n"); #endif #ifdef ZSTD_LZMACOMPRESS - DISPLAY( "--format=xz : compress files to the .xz format \n"); - DISPLAY( "--format=lzma : compress files to the .lzma format \n"); + DISPLAYOUT( "--format=xz : compress files to the .xz format \n"); + DISPLAYOUT( "--format=lzma : compress files to the .lzma format \n"); #endif #ifdef ZSTD_LZ4COMPRESS - DISPLAY( "--format=lz4 : compress files to the .lz4 format \n"); + DISPLAYOUT( "--format=lz4 : compress files to the .lz4 format \n"); #endif #ifndef ZSTD_NODECOMPRESS - DISPLAY( "--test : test compressed file integrity \n"); + DISPLAYOUT( "--test : test compressed file integrity \n"); #if ZSTD_SPARSE_DEFAULT - DISPLAY( "--[no-]sparse : sparse mode (default: enabled on file, disabled on stdout)\n"); + DISPLAYOUT( "--[no-]sparse : sparse mode (default: enabled on file, disabled on stdout)\n"); #else - DISPLAY( "--[no-]sparse : sparse mode (default: disabled)\n"); + DISPLAYOUT( "--[no-]sparse : sparse mode (default: disabled)\n"); #endif #endif - DISPLAY( " -M# : Set a memory usage limit for decompression \n"); - DISPLAY( "--no-progress : do not display the progress bar \n"); - DISPLAY( "-- : All arguments after \"--\" are treated as files \n"); + DISPLAYOUT( " -M# : Set a memory usage limit for decompression \n"); + DISPLAYOUT( "--no-progress : do not display the progress bar \n"); + DISPLAYOUT( "-- : All arguments after \"--\" are treated as files \n"); #ifndef ZSTD_NODICT - DISPLAY( "\n"); - DISPLAY( "Dictionary builder : \n"); - DISPLAY( "--train ## : create a dictionary from a training set of files \n"); - DISPLAY( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args\n"); - DISPLAY( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args\n"); - DISPLAY( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel); - DISPLAY( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName); - DISPLAY( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize); - DISPLAY( "--dictID=# : force dictionary ID to specified value (default: random)\n"); + DISPLAYOUT( "\n"); + DISPLAYOUT( "Dictionary builder : \n"); + DISPLAYOUT( "--train ## : create a dictionary from a training set of files \n"); + DISPLAYOUT( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args\n"); + DISPLAYOUT( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args\n"); + DISPLAYOUT( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel); + DISPLAYOUT( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName); + DISPLAYOUT( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize); + DISPLAYOUT( "--dictID=# : force dictionary ID to specified value (default: random)\n"); #endif #ifndef ZSTD_NOBENCH - DISPLAY( "\n"); - DISPLAY( "Benchmark arguments : \n"); - DISPLAY( " -b# : benchmark file(s), using # compression level (default: %d) \n", ZSTDCLI_CLEVEL_DEFAULT); - DISPLAY( " -e# : test all compression levels from -bX to # (default: 1)\n"); - DISPLAY( " -i# : minimum evaluation time in seconds (default: 3s) \n"); - DISPLAY( " -B# : cut file into independent blocks of size # (default: no block)\n"); - DISPLAY( "--priority=rt : set process priority to real-time \n"); + DISPLAYOUT( "\n"); + DISPLAYOUT( "Benchmark arguments : \n"); + DISPLAYOUT( " -b# : benchmark file(s), using # compression level (default: %d) \n", ZSTDCLI_CLEVEL_DEFAULT); + DISPLAYOUT( " -e# : test all compression levels from -bX to # (default: 1)\n"); + DISPLAYOUT( " -i# : minimum evaluation time in seconds (default: 3s) \n"); + DISPLAYOUT( " -B# : cut file into independent blocks of size # (default: no block)\n"); + DISPLAYOUT( "--priority=rt : set process priority to real-time \n"); #endif - return 0; } -static int badusage(const char* programName) +static void badusage(const char* programName) { - DISPLAYLEVEL(1, "Incorrect parameters\n"); - if (g_displayLevel >= 2) usage(programName); - return 1; + DISPLAYLEVEL(1, "Incorrect parameters \n"); + if (g_displayLevel >= 2) usage(stderr, programName); } static void waitEnter(void) { int unused; - DISPLAY("Press enter to continue...\n"); + DISPLAY("Press enter to continue... \n"); unused = getchar(); (void)unused; } @@ -479,42 +481,43 @@ static unsigned parseCompressionParameters(const char* stringPtr, ZSTD_compressi static void printVersion(void) { - DISPLAY(WELCOME_MESSAGE); + DISPLAYOUT(WELCOME_MESSAGE); + if (g_displayLevel >= 3) { /* format support */ - DISPLAYLEVEL(3, "*** supports: zstd"); -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8) - DISPLAYLEVEL(3, ", zstd legacy v0.%d+", ZSTD_LEGACY_SUPPORT); -#endif -#ifdef ZSTD_GZCOMPRESS - DISPLAYLEVEL(3, ", gzip"); -#endif -#ifdef ZSTD_LZ4COMPRESS - DISPLAYLEVEL(3, ", lz4"); -#endif -#ifdef ZSTD_LZMACOMPRESS - DISPLAYLEVEL(3, ", lzma, xz "); -#endif - DISPLAYLEVEL(3, "\n"); - /* posix support */ -#ifdef _POSIX_C_SOURCE - DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); -#endif -#ifdef _POSIX_VERSION - DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL \n", (long) _POSIX_VERSION); -#endif -#ifdef PLATFORM_POSIX_VERSION - DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); -#endif + DISPLAYOUT("*** supports: zstd"); + #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>0) && (ZSTD_LEGACY_SUPPORT<8) + DISPLAYOUT(", zstd legacy v0.%d+", ZSTD_LEGACY_SUPPORT); + #endif + #ifdef ZSTD_GZCOMPRESS + DISPLAYOUT(", gzip"); + #endif + #ifdef ZSTD_LZ4COMPRESS + DISPLAYOUT(", lz4"); + #endif + #ifdef ZSTD_LZMACOMPRESS + DISPLAYOUT(", lzma, xz "); + #endif + DISPLAYOUT("\n"); + if (g_displayLevel >= 4) { + /* posix support */ + #ifdef _POSIX_C_SOURCE + DISPLAYOUT("_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); + #endif + #ifdef _POSIX_VERSION + DISPLAYOUT("_POSIX_VERSION defined: %ldL \n", (long) _POSIX_VERSION); + #endif + #ifdef PLATFORM_POSIX_VERSION + DISPLAYOUT("PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); + #endif + } } } /* Environment variables for parameter setting */ #define ENV_CLEVEL "ZSTD_CLEVEL" -/* pick up environment variables - * requirement : g_displayOut must be set */ +/* pick up environment variable */ static int init_cLevel(void) { const char* const env = getenv(ENV_CLEVEL); - assert(g_displayOut == stderr); /* to print error messages */ if (env != NULL) { const char* ptr = env; int sign = 1; @@ -584,7 +587,7 @@ int main(int const argCount, const char* argv[]) FIO_prefs_t* const prefs = FIO_createPreferences(); zstd_operation_mode operation = zom_compress; ZSTD_compressionParameters compressionParams; - int cLevel; + int cLevel = init_cLevel(); int cLevelLast = MINCLEVEL - 1; /* lower than minimum */ unsigned recursive = 0; unsigned memLimit = 0; @@ -618,8 +621,6 @@ int main(int const argCount, const char* argv[]) (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */ assert(argCount >= 1); if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAY("zstd: allocation error \n"); exit(1); } - g_displayOut = stderr; - cLevel = init_cLevel(); /* must be done after setting g_displayOut, since some error message might be printed */ programName = lastNameFromPath(programName); #ifdef ZSTD_MULTITHREAD nbWorkers = 1; @@ -671,8 +672,8 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--decompress")) { operation=zom_decompress; continue; } if (!strcmp(argument, "--uncompress")) { operation=zom_decompress; continue; } if (!strcmp(argument, "--force")) { FIO_overwriteMode(prefs); forceStdout=1; followLinks=1; continue; } - if (!strcmp(argument, "--version")) { g_displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); } - if (!strcmp(argument, "--help")) { g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); } + if (!strcmp(argument, "--version")) { printVersion(); CLEAN_RETURN(0); } + if (!strcmp(argument, "--help")) { usage_advanced(programName); CLEAN_RETURN(0); } if (!strcmp(argument, "--verbose")) { g_displayLevel++; continue; } if (!strcmp(argument, "--quiet")) { g_displayLevel--; continue; } if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; g_displayLevel-=(g_displayLevel==2); continue; } @@ -691,7 +692,7 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } - if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) CLEAN_RETURN(badusage(programName)); continue; } + if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } if (!strcmp(argument, "--format=zstd")) { suffix = ZSTD_EXTENSION; FIO_setCompressionType(prefs, FIO_zstdCompression); continue; } #ifdef ZSTD_GZCOMPRESS @@ -718,8 +719,8 @@ int main(int const argCount, const char* argv[]) dict = cover; /* Allow optional arguments following an = */ if (*argument == 0) { memset(&coverParams, 0, sizeof(coverParams)); } - else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); } - else if (!parseCoverParameters(argument, &coverParams)) { CLEAN_RETURN(badusage(programName)); } + else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); } + else if (!parseCoverParameters(argument, &coverParams)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (longCommandWArg(&argument, "--train-fastcover")) { @@ -729,8 +730,8 @@ int main(int const argCount, const char* argv[]) dict = fastCover; /* Allow optional arguments following an = */ if (*argument == 0) { memset(&fastCoverParams, 0, sizeof(fastCoverParams)); } - else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); } - else if (!parseFastCoverParameters(argument, &fastCoverParams)) { CLEAN_RETURN(badusage(programName)); } + else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); } + else if (!parseFastCoverParameters(argument, &fastCoverParams)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (longCommandWArg(&argument, "--train-legacy")) { @@ -740,8 +741,8 @@ int main(int const argCount, const char* argv[]) dict = legacy; /* Allow optional arguments following an = */ if (*argument == 0) { continue; } - else if (*argument++ != '=') { CLEAN_RETURN(badusage(programName)); } - else if (!parseLegacyParameters(argument, &dictSelect)) { CLEAN_RETURN(badusage(programName)); } + else if (*argument++ != '=') { badusage(programName); CLEAN_RETURN(1); } + else if (!parseLegacyParameters(argument, &dictSelect)) { badusage(programName); CLEAN_RETURN(1); } continue; } #endif @@ -752,7 +753,7 @@ int main(int const argCount, const char* argv[]) if (longCommandWArg(&argument, "--block-size=")) { blockSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--dictID=")) { dictID = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) CLEAN_RETURN(badusage(programName)); continue; } + if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (longCommandWArg(&argument, "--stream-size=")) { streamSrcSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readU32FromChar(&argument); continue; } @@ -766,7 +767,8 @@ int main(int const argCount, const char* argv[]) ldmWindowLog = readU32FromChar(&argument); } else if (*argument != 0) { /* Invalid character following --long */ - CLEAN_RETURN(badusage(programName)); + badusage(programName); + CLEAN_RETURN(1); } /* Only set windowLog if not already set by --zstd */ if (compressionParams.windowLog == 0) @@ -783,13 +785,15 @@ int main(int const argCount, const char* argv[]) fastLevel = readU32FromChar(&argument); if (fastLevel > maxFast) fastLevel = maxFast; if (fastLevel) { - dictCLevel = cLevel = -(int)fastLevel; + dictCLevel = cLevel = -(int)fastLevel; } else { - CLEAN_RETURN(badusage(programName)); + badusage(programName); + CLEAN_RETURN(1); } } else if (*argument != 0) { /* Invalid character following --fast */ - CLEAN_RETURN(badusage(programName)); + badusage(programName); + CLEAN_RETURN(1); } else { cLevel = -1; /* default for --fast */ } @@ -822,9 +826,9 @@ int main(int const argCount, const char* argv[]) switch(argument[0]) { /* Display help */ - case 'V': g_displayOut=stdout; printVersion(); CLEAN_RETURN(0); /* Version Only */ + case 'V': printVersion(); CLEAN_RETURN(0); /* Version Only */ case 'H': - case 'h': g_displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); + case 'h': usage_advanced(programName); CLEAN_RETURN(0); /* Compress */ case 'z': operation=zom_compress; argument++; break; @@ -939,7 +943,7 @@ int main(int const argCount, const char* argv[]) break; /* unknown command */ - default : CLEAN_RETURN(badusage(programName)); + default : badusage(programName); CLEAN_RETURN(1); } } continue; @@ -1141,14 +1145,18 @@ int main(int const argCount, const char* argv[]) outFileName = stdoutmark; /* when input is stdin, default output is stdout */ /* Check if input/output defined as console; trigger an error in this case */ - if (!strcmp(filenames->fileNames[0], stdinmark) && IS_CONSOLE(stdin) ) - CLEAN_RETURN(badusage(programName)); + if (!strcmp(filenames->fileNames[0], stdinmark) && IS_CONSOLE(stdin) ) { + badusage(programName); + CLEAN_RETURN(1); + } if ( outFileName && !strcmp(outFileName, stdoutmark) && IS_CONSOLE(stdout) && !strcmp(filenames->fileNames[0], stdinmark) && !forceStdout - && operation!=zom_decompress ) - CLEAN_RETURN(badusage(programName)); + && operation!=zom_decompress ) { + badusage(programName); + CLEAN_RETURN(1); + } #ifndef ZSTD_NOCOMPRESS /* check compression level limits */ @@ -1197,12 +1205,11 @@ int main(int const argCount, const char* argv[]) } else { /* decompression or test */ #ifndef ZSTD_NODECOMPRESS if (memLimit == 0) { - if (compressionParams.windowLog == 0) + if (compressionParams.windowLog == 0) { memLimit = (U32)1 << g_defaultMaxWindowLog; - else { + } else { memLimit = (U32)1 << (compressionParams.windowLog & 31); - } - } + } } FIO_setMemLimit(prefs, memLimit); if (filenames->tableSize == 1 && outFileName) { operationResult = FIO_decompressFilename(prefs, outFileName, filenames->fileNames[0], dictFileName); diff --git a/tests/playTests.sh b/tests/playTests.sh index 4886aac2ba8..9e0d75d6c7d 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1173,6 +1173,17 @@ roundTripTest -g1M -P50 "1 --single-thread --long=29" " --long=28 --memory=512MB roundTripTest -g1M -P50 "1 --single-thread --long=29" " --zstd=wlog=28 --memory=512MB" + + +if [ "$1" != "--test-large-data" ]; then + println "Skipping large data tests" + exit 0 +fi + + +############################################################################# + + if [ -n "$hasMT" ] then println "\n===> adaptive mode " @@ -1190,14 +1201,6 @@ then fi -if [ "$1" != "--test-large-data" ]; then - println "Skipping large data tests" - exit 0 -fi - - -############################################################################# - println "\n===> large files tests " roundTripTest -g270000000 1 From 1fc9352f815802037b5fe461c5a31437a3dcb3ef Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 2 Dec 2019 21:39:06 -0800 Subject: [PATCH 124/402] Using bss var instead of creating new bool --- lib/compress/zstd_compress.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 34cfbe5e124..2348b1ab117 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2455,11 +2455,11 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, const void* src, size_t srcSize, U32 lastBlock) { size_t cSize = 0; - int compressSuperBlock = 1; + size_t bss; DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); - { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + { bss = ZSTD_buildSeqStore(zc, src, srcSize); FORWARD_IF_ERROR(bss); if (bss == ZSTDbss_compress) { cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); @@ -2471,7 +2471,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, */ if (cSize == 0) { cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); - compressSuperBlock = 0; + bss = ZSTDbss_noCompress; /* In compression, there is an assumption that a compressed block is always * within the size of ZSTD_compressBound(). However, SuperBlock compression * can exceed the limit due to overhead of headers from SubBlocks. @@ -2489,7 +2489,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, * compress normally. */ - compressSuperBlock = 1; + bss = ZSTDbss_compress; cSize = ZSTD_compressSequences(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, @@ -2500,7 +2500,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, FORWARD_IF_ERROR(cSize); if (cSize == 0) { - compressSuperBlock = 0; + bss = ZSTDbss_noCompress; /* If compressSequences didn't work, we just output a regular * uncompressed block */ cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); @@ -2513,7 +2513,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, } } - if (!ZSTD_isError(cSize) && compressSuperBlock) { + if (!ZSTD_isError(cSize) && bss == ZSTDbss_compress) { /* confirm repcodes and entropy tables when emitting a compressed block */ ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; zc->blockState.prevCBlock = zc->blockState.nextCBlock; From 5120883a9c29a7966bbd2144df04f6976f4c7acc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 3 Dec 2019 17:06:42 -0800 Subject: [PATCH 125/402] bumped version number so that potential issue report do not confuse `dev` with latest release --- CHANGELOG | 7 +++++++ lib/zstd.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 3b882d4cda5..588e34f9382 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +v1.4.5 +perf: Improved decompression speed, +10% on clang, +5% on gcc, by @terrelln +cli: new command : provide list of files to de/compress within a file with --filelist=FILE, by @AhmedAbdellah19 +api: low latency blocks, new experimental parameter by @ephiepark +build: mingw cross-compilation from unix, by @Ericson2314 +misc: bitflip analyzer tool, by @felixhandte + v1.4.4 perf: Improved decompression speed, by > 10%, by @terrelln perf: Better compression speed when re-using a context, by @felixhandte diff --git a/lib/zstd.h b/lib/zstd.h index f6f310150ce..73cb3d315d0 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -72,7 +72,7 @@ extern "C" { /*------ Version ------*/ #define ZSTD_VERSION_MAJOR 1 #define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 4 +#define ZSTD_VERSION_RELEASE 5 #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ From 49c6d492479227644e60c2caa15a6334f302f6ea Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 4 Dec 2019 10:02:17 -0800 Subject: [PATCH 126/402] [fuzz] msan uninitialized unsigned value (#1908) Fixes new fuzz issue Credit to OSS-Fuzz * Initializing unsigned value * Initialilzing to 1 instead of 0 because its more conservative * Unconditionoally setting to check first and then checking zero * Moving bool to before block for c90 * Move check set before block --- lib/compress/zstd_compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 682c9c047d0..16476f6fa9e 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2858,9 +2858,10 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; dictPtr += 8; + bs->entropy.huf.repeatMode = HUF_repeat_check; { unsigned maxSymbolValue = 255; - unsigned hasZeroWeights; + unsigned hasZeroWeights = 1; size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr, &hasZeroWeights); @@ -2868,7 +2869,6 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, * weights. Otherwise, we set it to check */ if (!hasZeroWeights) bs->entropy.huf.repeatMode = HUF_repeat_valid; - else bs->entropy.huf.repeatMode = HUF_repeat_check; RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted); RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted); From ffb0463041e7fa0e2d2cea55e908b7e00a968d4d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 4 Dec 2019 14:52:27 -0800 Subject: [PATCH 127/402] Refactor --- lib/compress/zstd_compress.c | 134 +++++++++++++++++------------------ 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 2348b1ab117..2f28b8365dc 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2450,82 +2450,80 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, return cSize; } -static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, +static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) +{ + ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; + zc->blockState.prevCBlock = zc->blockState.nextCBlock; + zc->blockState.nextCBlock = tmp; +} + +static size_t ZSTD_compressBlock_targetCBlockSize_init(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize, - U32 lastBlock) { - size_t cSize = 0; - size_t bss; - DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", - (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); + U32 lastBlock) +{ + const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + FORWARD_IF_ERROR(bss); + if (bss == ZSTDbss_compress) + return ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); + return 0; +} - { bss = ZSTD_buildSeqStore(zc, src, srcSize); - FORWARD_IF_ERROR(bss); - if (bss == ZSTDbss_compress) { - cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); - } } +static void ZSTD_compressBlock_targetCBlockSize_end(ZSTD_CCtx* zc) +{ + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; +} - /* Superblock compression may fail, in which case - * encode using ZSTD_noCompressSuperBlock writing sub blocks - * in uncompressed mode. - */ - if (cSize == 0) { - cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); - bss = ZSTDbss_noCompress; - /* In compression, there is an assumption that a compressed block is always - * within the size of ZSTD_compressBound(). However, SuperBlock compression - * can exceed the limit due to overhead of headers from SubBlocks. - * This breaks in streaming mode where output buffer in compress context is - * allocated ZSTD_compressBound() amount of memory, which may not be big - * enough for SuperBlock compression. - * In such case, fall back to normal compression. This is possible because - * targetCBlockSize is best effort not a guarantee. */ - if (cSize == ERROR(dstSize_tooSmall) || (dstCapacity - cSize) < 4) { - /* We check (dstCapacity - cSize) >= 4 above because we have to make sure - * to leave enough room for the checksum that will eventually get added in - * the epilogue. Otherwise, we're just going to throw the dstSize_tooSmall - * error there instead of here */ - BYTE* const ostart = (BYTE*)dst; - /* If ZSTD_noCompressSuperBlock fails with dstSize_tooSmall, - * compress normally. - */ - bss = ZSTDbss_compress; - cSize = ZSTD_compressSequences(&zc->seqStore, - &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, - &zc->appliedParams, - ostart+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, - srcSize, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, - zc->bmi2); - - FORWARD_IF_ERROR(cSize); - if (cSize == 0) { - bss = ZSTDbss_noCompress; - /* If compressSequences didn't work, we just output a regular - * uncompressed block */ - cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); - FORWARD_IF_ERROR(cSize); - } else { - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24(ostart, cBlockHeader24); - cSize += ZSTD_blockHeaderSize; - } - } +static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, + size_t cSize, void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastBlock) +{ + /* Superblock compression was successful */ + if (cSize != 0) { + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; } - if (!ZSTD_isError(cSize) && bss == ZSTDbss_compress) { - /* confirm repcodes and entropy tables when emitting a compressed block */ - ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; - zc->blockState.prevCBlock = zc->blockState.nextCBlock; - zc->blockState.nextCBlock = tmp; + /* Superblock compression failed, attempt to emit noCompress superblocks + * and return early if that is successful and we have enough room for checksum */ + cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); + if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) + return cSize; + + /* noCompress superblock emission failed. Attempt to compress normally + * and return early if that is successful */ + cSize = ZSTD_compressSequences(&zc->seqStore, + &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, (BYTE*)dst+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, + srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE, zc->bmi2); + FORWARD_IF_ERROR(cSize); + if (cSize != 0) { + U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24((BYTE*)dst, cBlockHeader24); + cSize += ZSTD_blockHeaderSize; + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; } - /* We check that dictionaries have offset codes available for the first - * block. After the first block, the offcode table might not have large - * enough codes to represent the offsets in the data. - */ - if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) - zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + /* Everything failed. Just emit a regular noCompress block */ + return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); +} + +static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastBlock) +{ + size_t cSize = 0; + DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); + cSize = ZSTD_compressBlock_targetCBlockSize_init(zc, dst, dstCapacity, src, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize); + cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, cSize, dst, dstCapacity, src, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize); + ZSTD_compressBlock_targetCBlockSize_end(zc); return cSize; } From 2ec556fec2fcde585f307f6eae4dfa08cd4d46f4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 4 Dec 2019 15:23:13 -0800 Subject: [PATCH 128/402] Moving init/end functions, moving compressSuperBlock inside body() --- lib/compress/zstd_compress.c | 78 +++++++++++++++++------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 2f28b8365dc..52badd5bc82 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2457,54 +2457,46 @@ static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) zc->blockState.nextCBlock = tmp; } -static size_t ZSTD_compressBlock_targetCBlockSize_init(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - U32 lastBlock) -{ - const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); - FORWARD_IF_ERROR(bss); - if (bss == ZSTDbss_compress) - return ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); - return 0; -} - -static void ZSTD_compressBlock_targetCBlockSize_end(ZSTD_CCtx* zc) -{ - if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) - zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; -} - static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, - size_t cSize, void* dst, size_t dstCapacity, + const size_t bss, void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock) { - /* Superblock compression was successful */ - if (cSize != 0) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; + /* Attempt superblock compression and return early if successful */ + { + if (bss == ZSTDbss_compress) { + size_t cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); + FORWARD_IF_ERROR(cSize); + if (cSize != 0) { + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; + } + } } /* Superblock compression failed, attempt to emit noCompress superblocks * and return early if that is successful and we have enough room for checksum */ - cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); - if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) - return cSize; + { + size_t cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); + if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) + return cSize; + } /* noCompress superblock emission failed. Attempt to compress normally * and return early if that is successful */ - cSize = ZSTD_compressSequences(&zc->seqStore, - &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, - &zc->appliedParams, (BYTE*)dst+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, - srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE, zc->bmi2); - FORWARD_IF_ERROR(cSize); - if (cSize != 0) { - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24((BYTE*)dst, cBlockHeader24); - cSize += ZSTD_blockHeaderSize; - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; + { + size_t cSize = ZSTD_compressSequences(&zc->seqStore, + &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, (BYTE*)dst+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, + srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE, zc->bmi2); + FORWARD_IF_ERROR(cSize); + if (cSize != 0) { + U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24((BYTE*)dst, cBlockHeader24); + cSize += ZSTD_blockHeaderSize; + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; + } } /* Everything failed. Just emit a regular noCompress block */ @@ -2517,13 +2509,17 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, U32 lastBlock) { size_t cSize = 0; + const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); - cSize = ZSTD_compressBlock_targetCBlockSize_init(zc, dst, dstCapacity, src, srcSize, lastBlock); - FORWARD_IF_ERROR(cSize); - cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, cSize, dst, dstCapacity, src, srcSize, lastBlock); + FORWARD_IF_ERROR(bss); + + cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, bss, dst, dstCapacity, src, srcSize, lastBlock); FORWARD_IF_ERROR(cSize); - ZSTD_compressBlock_targetCBlockSize_end(zc); + + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + return cSize; } From e1913dc87fe8cff6e623a5ee44c69e44e5e098c2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 4 Dec 2019 15:51:17 -0800 Subject: [PATCH 129/402] Making const, removing unnecessary indent, changing parameter order --- lib/compress/zstd_compress.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 52badd5bc82..20fbdb10db1 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2458,26 +2458,24 @@ static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) } static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, - const size_t bss, void* dst, size_t dstCapacity, + void* dst, size_t dstCapacity, const void* src, size_t srcSize, - U32 lastBlock) + const size_t bss, U32 lastBlock) { /* Attempt superblock compression and return early if successful */ - { - if (bss == ZSTDbss_compress) { - size_t cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); - FORWARD_IF_ERROR(cSize); - if (cSize != 0) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; - } + if (bss == ZSTDbss_compress) { + size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); + FORWARD_IF_ERROR(cSize); + if (cSize != 0) { + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; } } /* Superblock compression failed, attempt to emit noCompress superblocks * and return early if that is successful and we have enough room for checksum */ { - size_t cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); + size_t const cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) return cSize; } @@ -2485,7 +2483,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, /* noCompress superblock emission failed. Attempt to compress normally * and return early if that is successful */ { - size_t cSize = ZSTD_compressSequences(&zc->seqStore, + size_t const cSize = ZSTD_compressSequences(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, (BYTE*)dst+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE, zc->bmi2); @@ -2493,9 +2491,8 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, if (cSize != 0) { U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); MEM_writeLE24((BYTE*)dst, cBlockHeader24); - cSize += ZSTD_blockHeaderSize; ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; + return cSize + ZSTD_blockHeaderSize; } } @@ -2514,7 +2511,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); FORWARD_IF_ERROR(bss); - cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, bss, dst, dstCapacity, src, srcSize, lastBlock); + cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock); FORWARD_IF_ERROR(cSize); if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) From 23e997439a31b740b7e97b74cc218b33988915d0 Mon Sep 17 00:00:00 2001 From: "Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)" Date: Fri, 6 Dec 2019 16:14:33 +0000 Subject: [PATCH 130/402] Make idiomatic cmake install so third party cmake installers work right. --- build/cmake/lib/CMakeLists.txt | 38 ++++++++++++++++++++++++++------- build/cmake/lib/config.cmake.in | 7 ++++++ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 build/cmake/lib/config.cmake.in diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 7adca875c52..e92647bf186 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -127,6 +127,7 @@ if (ZSTD_BUILD_STATIC) set_target_properties( libzstd_static PROPERTIES + POSITION_INDEPENDENT_CODE On OUTPUT_NAME ${STATIC_LIBRARY_BASE_NAME}) endif () @@ -146,22 +147,43 @@ endif () # install target install(FILES - ${LIBRARY_DIR}/zstd.h - ${LIBRARY_DIR}/deprecated/zbuff.h - ${LIBRARY_DIR}/dictBuilder/zdict.h - ${LIBRARY_DIR}/dictBuilder/cover.h - ${LIBRARY_DIR}/common/zstd_errors.h + "${LIBRARY_DIR}/zstd.h" + "${LIBRARY_DIR}/deprecated/zbuff.h" + "${LIBRARY_DIR}/dictBuilder/zdict.h" + "${LIBRARY_DIR}/dictBuilder/cover.h" + "${LIBRARY_DIR}/common/zstd_errors.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") if (ZSTD_BUILD_SHARED) - install(TARGETS libzstd_shared RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + install(TARGETS libzstd_shared EXPORT zstdExports + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") + ) endif() if (ZSTD_BUILD_STATIC) - install(TARGETS libzstd_static ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install(TARGETS libzstd_static EXPORT zstdExports + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ) endif () +# export targets + find config +configure_file( + "config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake" + @ONLY +) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zstd" +) +install(EXPORT zstdExports + NAMESPACE zstd:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zstd" +) + # uninstall target if (NOT TARGET uninstall) configure_file( diff --git a/build/cmake/lib/config.cmake.in b/build/cmake/lib/config.cmake.in new file mode 100644 index 00000000000..3a22756fcc9 --- /dev/null +++ b/build/cmake/lib/config.cmake.in @@ -0,0 +1,7 @@ +include(FindPackageHandleStandardArgs) +set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE}) +find_package_handle_standard_args(zstd CONFIG_MODE) + +if(NOT TARGET zstd::libzstd_shared) + include("${CMAKE_CURRENT_LIST_DIR}/zstdExports.cmake") +endif() From e3cd2785e2caaf51d815d750a789215a850ddbda Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 15:31:29 -0800 Subject: [PATCH 131/402] Add test to catch too many noCompress superblocks on streaming --- tests/fuzzer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 56936e9f0ca..89bac525c8c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -489,6 +489,53 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d: superblock uncompressable data, too many nocompress superblocks : ", testNb++) + { + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + void* src = CNBuffer; void* dst = compressedBuffer; + size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize); + + /* This is the number of bytes to stream before ending. This value + * was obtained by trial and error :/. */ + + const size_t streamCompressThreshold = 161792; + const size_t streamCompressDelta = 1024; + + /* The first 1/3 of the buffer is compressable and the last 2/3 is + * uncompressable. This is an approximation of the type of data + * the fuzzer generated to catch this bug. Streams like this were making + * zstd generate noCompress superblocks (which are larger than the src + * they come from). Do this enough times, and we'll run out of room + * and throw a dstSize_tooSmall error. */ + + const size_t compressablePartSize = srcSize/3; + const size_t uncompressablePartSize = srcSize-compressablePartSize; + RDG_genBuffer(CNBuffer, compressablePartSize, 0.5, 0.5, seed); + RDG_genBuffer(CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); + + /* Setting target block size so that superblock is used */ + + ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 81); + + { size_t read; + for (read = 0; read < streamCompressThreshold; read += streamCompressDelta) { + ZSTD_inBuffer in = {src, streamCompressDelta, 0}; + ZSTD_outBuffer out = {dst, dstCapacity, 0}; + assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue))); + assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end))); + src += streamCompressDelta; srcSize -= streamCompressDelta; + dst += out.pos; dstCapacity -= out.pos;}} + + /* This is trying to catch a dstSize_tooSmall error */ + + { ZSTD_inBuffer in = {src, srcSize, 0}; + ZSTD_outBuffer out = {dst, dstCapacity, 0}; + assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)));} + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + + RDG_genBuffer(CNBuffer, CNBuffSize, compressibility, 0. /*auto*/, seed); DISPLAYLEVEL(3, "test%3d: superblock enough room for checksum : ", testNb++) { /* This tests whether or not we leave enough room for the checksum at the end @@ -501,7 +548,7 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeCCtx(cctx); } DISPLAYLEVEL(3, "OK \n"); - + DISPLAYLEVEL(3, "test%3i : compress a NULL input with each level : ", testNb++); { int level = -1; ZSTD_CCtx* cctx = ZSTD_createCCtx(); From 5225dcfc0f8c03ea718417d58c81cd0c799abf22 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 15:47:28 -0800 Subject: [PATCH 132/402] Adding bool to check if enough room left for noCompress superblocks --- lib/compress/zstd_compress.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b624e3c1861..338f8dd5662 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2562,6 +2562,14 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, BYTE* const ostart = (BYTE*)dst; BYTE* op = ostart; U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; + + /* This bool is set if there is enough room to output all noCompress superblocks. + * Just checks if the number of compressed blocks we can fit in dstCapacity is + * greater than the optimistic number of blocks we still have remaining. + * This might be UNset when data is uncompressable and we're streaming. */ + + int enoughDstCapacityForNoCompressSuperBlocks = + (dstCapacity / (blockSize + 7 /* header + checksum */)) > (srcSize / blockSize); assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); @@ -2586,7 +2594,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, { size_t cSize; int useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); - if (useTargetCBlockSize) { + if (useTargetCBlockSize && enoughDstCapacityForNoCompressSuperBlocks) { cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cSize); } else { From 49b2bf7106a9080b9dd121bea9359473fa5c1321 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 16:06:57 -0800 Subject: [PATCH 133/402] 'void* size issue' fix --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 89bac525c8c..c39969a8d99 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -511,7 +511,7 @@ static int basicUnitTests(U32 const seed, double compressibility) const size_t compressablePartSize = srcSize/3; const size_t uncompressablePartSize = srcSize-compressablePartSize; RDG_genBuffer(CNBuffer, compressablePartSize, 0.5, 0.5, seed); - RDG_genBuffer(CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); + RDG_genBuffer((void*)((char*)CNBuffer+compressablePartSize), uncompressablePartSize, 0, 0, seed); /* Setting target block size so that superblock is used */ From db5124ef6e6d5ca97df957280930a3591021b1bb Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 16:24:49 -0800 Subject: [PATCH 134/402] More void* issues. Just replacing with BYTE* --- tests/fuzzer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index c39969a8d99..d413be04084 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -492,7 +492,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3d: superblock uncompressable data, too many nocompress superblocks : ", testNb++) { ZSTD_CCtx* cctx = ZSTD_createCCtx(); - void* src = CNBuffer; void* dst = compressedBuffer; + BYTE* src = CNBuffer; BYTE* dst = compressedBuffer; size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize); /* This is the number of bytes to stream before ending. This value @@ -511,7 +511,7 @@ static int basicUnitTests(U32 const seed, double compressibility) const size_t compressablePartSize = srcSize/3; const size_t uncompressablePartSize = srcSize-compressablePartSize; RDG_genBuffer(CNBuffer, compressablePartSize, 0.5, 0.5, seed); - RDG_genBuffer((void*)((char*)CNBuffer+compressablePartSize), uncompressablePartSize, 0, 0, seed); + RDG_genBuffer(CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); /* Setting target block size so that superblock is used */ From 4399eed42e06ebcf0cfc8ef60350e0e98fc149a2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 16:38:11 -0800 Subject: [PATCH 135/402] Adding explict cast to satisfy appveyor ci --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index d413be04084..47d0e012a0b 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -492,7 +492,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3d: superblock uncompressable data, too many nocompress superblocks : ", testNb++) { ZSTD_CCtx* cctx = ZSTD_createCCtx(); - BYTE* src = CNBuffer; BYTE* dst = compressedBuffer; + BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize); /* This is the number of bytes to stream before ending. This value From 989ce13e190e446996379a96758b70562540ba26 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Dec 2019 16:50:21 -0800 Subject: [PATCH 136/402] One more type conversion --- tests/fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 47d0e012a0b..7880c5d43be 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -511,7 +511,7 @@ static int basicUnitTests(U32 const seed, double compressibility) const size_t compressablePartSize = srcSize/3; const size_t uncompressablePartSize = srcSize-compressablePartSize; RDG_genBuffer(CNBuffer, compressablePartSize, 0.5, 0.5, seed); - RDG_genBuffer(CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); + RDG_genBuffer((BYTE*)CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); /* Setting target block size so that superblock is used */ From 3746693b71b135bb060f40483cd22b0cebdd4d3d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 14 Dec 2019 13:29:24 -0800 Subject: [PATCH 137/402] added ppc64le tests on travis on real hardware --- .gitignore | 3 ++- .travis.yml | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6ad56430467..96f8bdce8e0 100644 --- a/.gitignore +++ b/.gitignore @@ -44,5 +44,6 @@ _zstdbench/ googletest/ *.d *.vscode +*.code-workspace compile_commands.json -.clangd \ No newline at end of file +.clangd diff --git a/.travis.yml b/.travis.yml index 57242a488ac..a87c604aa83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -152,6 +152,7 @@ matrix: # tests for master branch and cron job only - name: OS-X # ~13mn + if: branch = master os: osx script: - make test @@ -168,12 +169,19 @@ matrix: - CC=clang-3.8 make tsan-test-zstream - CC=clang-3.8 make tsan-fuzztest - - name: PPC64 # ~13mn + - name: Qemu PPC64 + Fuzz test # ~13mn if: branch = master script: - make ppcinstall - make ppc64fuzz + - name: PPC64LE + Fuzz test # ~13mn + if: branch = master + arch: ppc64le + script: + - cat /proc/cpuinfo + - make test + # note : we already have aarch64 tests on hardware - name: Qemu aarch64 + Fuzz Test (on Xenial) # ~14mn if: branch = master From 4584c88a99a7c8f8df75877321a35c0a9367a9c5 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 17 Dec 2019 11:26:18 -0800 Subject: [PATCH 138/402] Don't Rely on Implicit Return in Main --- contrib/diagnose_corruption/check_flipped_bits.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c index 8555959e418..23b53287fc7 100644 --- a/contrib/diagnose_corruption/check_flipped_bits.c +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -214,4 +214,6 @@ int main(int argc, char* argv[]) { perturb_bytes(&stuff); free_stuff(&stuff); + + return 0; } \ No newline at end of file From 56415efc76b8407df39e872b2f5bf65c6badf507 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 17 Dec 2019 17:16:51 -0800 Subject: [PATCH 139/402] Constifying, malloc check and naming nit --- lib/compress/zstd_compress.c | 2 +- tests/fuzzer.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 338f8dd5662..a674cea4022 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2568,7 +2568,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, * greater than the optimistic number of blocks we still have remaining. * This might be UNset when data is uncompressable and we're streaming. */ - int enoughDstCapacityForNoCompressSuperBlocks = + const int enoughDstCapacityForNoCompressSuperBlocks = (dstCapacity / (blockSize + 7 /* header + checksum */)) > (srcSize / blockSize); assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 7880c5d43be..337455d9f71 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -489,10 +489,10 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3d: superblock uncompressable data, too many nocompress superblocks : ", testNb++) + DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++) { - ZSTD_CCtx* cctx = ZSTD_createCCtx(); - BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; size_t srcSize = 321656; size_t dstCapacity = ZSTD_compressBound(srcSize); /* This is the number of bytes to stream before ending. This value @@ -501,20 +501,21 @@ static int basicUnitTests(U32 const seed, double compressibility) const size_t streamCompressThreshold = 161792; const size_t streamCompressDelta = 1024; - /* The first 1/3 of the buffer is compressable and the last 2/3 is - * uncompressable. This is an approximation of the type of data + /* The first 1/3 of the buffer is compressible and the last 2/3 is + * uncompressible. This is an approximation of the type of data * the fuzzer generated to catch this bug. Streams like this were making * zstd generate noCompress superblocks (which are larger than the src * they come from). Do this enough times, and we'll run out of room * and throw a dstSize_tooSmall error. */ - const size_t compressablePartSize = srcSize/3; - const size_t uncompressablePartSize = srcSize-compressablePartSize; - RDG_genBuffer(CNBuffer, compressablePartSize, 0.5, 0.5, seed); - RDG_genBuffer((BYTE*)CNBuffer+compressablePartSize, uncompressablePartSize, 0, 0, seed); + const size_t compressiblePartSize = srcSize/3; + const size_t uncompressiblePartSize = srcSize-compressiblePartSize; + RDG_genBuffer(CNBuffer, compressiblePartSize, 0.5, 0.5, seed); + RDG_genBuffer((BYTE*)CNBuffer+compressiblePartSize, uncompressiblePartSize, 0, 0, seed); /* Setting target block size so that superblock is used */ + assert(cctx != NULL); ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 81); { size_t read; From 18f03516b320f8f280877738830c7e14f27db52c Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 18 Dec 2019 11:29:53 -0800 Subject: [PATCH 140/402] Print Summary of Errors Encountered --- .../diagnose_corruption/check_flipped_bits.c | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c index 23b53287fc7..58f7a45d540 100644 --- a/contrib/diagnose_corruption/check_flipped_bits.c +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -9,6 +9,7 @@ */ #include "zstd.h" +#include "zstd_errors.h" #include #include @@ -27,6 +28,9 @@ typedef struct { size_t output_size; ZSTD_DCtx* dctx; + + int success_count; + int error_counts[ZSTD_error_maxCode]; } stuff_t; static void free_stuff(stuff_t* stuff) { @@ -40,6 +44,19 @@ static void usage(void) { exit(1); } +static void print_summary(stuff_t* stuff) { + int error_code; + fprintf(stderr, "%9d successful decompressions\n", stuff->success_count); + for (error_code = 0; error_code < ZSTD_error_maxCode; error_code++) { + int count = stuff->error_counts[error_code]; + if (count) { + fprintf( + stderr, "%9d failed decompressions with message: %s\n", + count, ZSTD_getErrorString(error_code)); + } + } +} + static char* readFile(const char* filename, size_t* size) { struct stat statbuf; int ret; @@ -121,6 +138,9 @@ static int init_stuff(stuff_t* stuff, int argc, char *argv[]) { return 0; } + stuff->success_count = 0; + memset(stuff->error_counts, 0, sizeof(stuff->error_counts)); + return 1; } @@ -138,6 +158,12 @@ static int test_decompress(stuff_t* stuff) { ret = ZSTD_decompressStream(dctx, &out, &in); if (ZSTD_isError(ret)) { + unsigned int code = ZSTD_getErrorCode(ret); + if (code >= ZSTD_error_maxCode) { + fprintf(stderr, "Received unexpected error code!\n"); + exit(1); + } + stuff->error_counts[code]++; /* fprintf( stderr, "Decompression failed: %s\n", ZSTD_getErrorName(ret)); @@ -146,6 +172,7 @@ static int test_decompress(stuff_t* stuff) { } } + stuff->success_count++; return 1; } @@ -155,7 +182,7 @@ static int perturb_bits(stuff_t* stuff) { for (pos = 0; pos < stuff->input_size; pos++) { unsigned char old_val = stuff->input[pos]; if (pos % 1000 == 0) { - fprintf(stderr, "Perturbing byte %zu\n", pos); + fprintf(stderr, "Perturbing byte %zu / %zu\n", pos, stuff->input_size); } for (bit = 0; bit < 8; bit++) { unsigned char new_val = old_val ^ (1 << bit); @@ -179,7 +206,7 @@ static int perturb_bytes(stuff_t* stuff) { for (pos = 0; pos < stuff->input_size; pos++) { unsigned char old_val = stuff->input[pos]; if (pos % 1000 == 0) { - fprintf(stderr, "Perturbing byte %zu\n", pos); + fprintf(stderr, "Perturbing byte %zu / %zu\n", pos, stuff->input_size); } for (new_val = 0; new_val < 256; new_val++) { stuff->perturbed[pos] = new_val; @@ -213,6 +240,8 @@ int main(int argc, char* argv[]) { perturb_bytes(&stuff); + print_summary(&stuff); + free_stuff(&stuff); return 0; From fe454c0a76aeb490072b9fbf00da186fc8b1812a Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 18 Dec 2019 11:26:35 -0800 Subject: [PATCH 141/402] Add Support for Dictionaries --- .../diagnose_corruption/check_flipped_bits.c | 157 +++++++++++++++++- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c index 58f7a45d540..78473ea59f5 100644 --- a/contrib/diagnose_corruption/check_flipped_bits.c +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -8,6 +8,7 @@ * You may select, at your option, one of the above-listed licenses. */ +#define ZSTD_STATIC_LINKING_ONLY #include "zstd.h" #include "zstd_errors.h" @@ -27,6 +28,13 @@ typedef struct { char *output; size_t output_size; + const char *dict_file_name; + const char *dict_file_dir_name; + int32_t dict_id; + char *dict; + size_t dict_size; + ZSTD_DDict* ddict; + ZSTD_DCtx* dctx; int success_count; @@ -36,11 +44,18 @@ typedef struct { static void free_stuff(stuff_t* stuff) { free(stuff->input); free(stuff->output); + ZSTD_freeDDict(stuff->ddict); + free(stuff->dict); ZSTD_freeDCtx(stuff->dctx); } static void usage(void) { - fprintf(stderr, "check_flipped_bits input_filename"); + fprintf(stderr, "check_flipped_bits input_filename [-d dict] [-D dict_dir]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Arguments:\n"); + fprintf(stderr, " -d file: path to a dictionary file to use.\n"); + fprintf(stderr, " -D dir : path to a directory, with files containing dictionaries, of the\n" + " form DICTID.zstd-dict, e.g., 12345.zstd-dict.\n"); exit(1); } @@ -104,10 +119,76 @@ static char* readFile(const char* filename, size_t* size) { return buf; } +static ZSTD_DDict* readDict(const char* filename, char **buf, size_t* size, int32_t* dict_id) { + ZSTD_DDict* ddict; + *buf = readFile(filename, size); + if (*buf == NULL) { + fprintf(stderr, "Opening dictionary file '%s' failed\n", filename); + return NULL; + } + + ddict = ZSTD_createDDict_advanced(*buf, *size, ZSTD_dlm_byRef, ZSTD_dct_auto, ZSTD_defaultCMem); + if (ddict == NULL) { + fprintf(stderr, "Failed to create ddict.\n"); + return NULL; + } + if (dict_id != NULL) { + *dict_id = ZSTD_getDictID_fromDDict(ddict); + } + return ddict; +} + +static ZSTD_DDict* readDictByID(stuff_t *stuff, int32_t dict_id, char **buf, size_t* size) { + if (stuff->dict_file_dir_name == NULL) { + return NULL; + } else { + size_t dir_name_len = strlen(stuff->dict_file_dir_name); + int dir_needs_separator = 0; + size_t dict_file_name_alloc_size = dir_name_len + 1 /* '/' */ + 10 /* max int32_t len */ + strlen(".zstd-dict") + 1 /* '\0' */; + char *dict_file_name = malloc(dict_file_name_alloc_size); + ZSTD_DDict* ddict; + int32_t read_dict_id; + if (dict_file_name == NULL) { + fprintf(stderr, "malloc failed.\n"); + return 0; + } + + if (dir_name_len > 0 && stuff->dict_file_dir_name[dir_name_len - 1] != '/') { + dir_needs_separator = 1; + } + + snprintf( + dict_file_name, + dict_file_name_alloc_size, + "%s%s%u.zstd-dict", + stuff->dict_file_dir_name, + dir_needs_separator ? "/" : "", + dict_id); + + /* fprintf(stderr, "Loading dict %u from '%s'.\n", dict_id, dict_file_name); */ + + ddict = readDict(dict_file_name, buf, size, &read_dict_id); + if (ddict == NULL) { + fprintf(stderr, "Failed to create ddict from '%s'.\n", dict_file_name); + free(dict_file_name); + return 0; + } + if (read_dict_id != dict_id) { + fprintf(stderr, "Read dictID (%u) does not match expected (%u).\n", read_dict_id, dict_id); + free(dict_file_name); + ZSTD_freeDDict(ddict); + return 0; + } + + free(dict_file_name); + return ddict; + } +} + static int init_stuff(stuff_t* stuff, int argc, char *argv[]) { const char* input_filename; - if (argc != 2) { + if (argc < 2) { usage(); } @@ -133,6 +214,51 @@ static int init_stuff(stuff_t* stuff, int argc, char *argv[]) { return 0; } + stuff->dict_file_name = NULL; + stuff->dict_file_dir_name = NULL; + stuff->dict_id = 0; + stuff->dict = NULL; + stuff->dict_size = 0; + stuff->ddict = NULL; + + if (argc > 2) { + if (!strcmp(argv[2], "-d")) { + if (argc > 3) { + stuff->dict_file_name = argv[3]; + } else { + usage(); + } + } else + if (!strcmp(argv[2], "-D")) { + if (argc > 3) { + stuff->dict_file_dir_name = argv[3]; + } else { + usage(); + } + } else { + usage(); + } + } + + if (stuff->dict_file_dir_name) { + int32_t dict_id = ZSTD_getDictID_fromFrame(stuff->input, stuff->input_size); + if (dict_id != 0) { + stuff->ddict = readDictByID(stuff, dict_id, &stuff->dict, &stuff->dict_size); + if (stuff->ddict == NULL) { + fprintf(stderr, "Failed to create cached ddict.\n"); + return 0; + } + stuff->dict_id = dict_id; + } + } else + if (stuff->dict_file_name) { + stuff->ddict = readDict(stuff->dict_file_name, &stuff->dict, &stuff->dict_size, &stuff->dict_id); + if (stuff->ddict == NULL) { + fprintf(stderr, "Failed to create ddict from '%s'.\n", stuff->dict_file_name); + return 0; + } + } + stuff->dctx = ZSTD_createDCtx(); if (stuff->dctx == NULL) { return 0; @@ -149,9 +275,23 @@ static int test_decompress(stuff_t* stuff) { ZSTD_inBuffer in = {stuff->perturbed, stuff->input_size, 0}; ZSTD_outBuffer out = {stuff->output, stuff->output_size, 0}; ZSTD_DCtx* dctx = stuff->dctx; + int32_t custom_dict_id = ZSTD_getDictID_fromFrame(in.src, in.size); + char *custom_dict = NULL; + size_t custom_dict_size = 0; + ZSTD_DDict* custom_ddict = NULL; + + if (custom_dict_id != 0 && custom_dict_id != stuff->dict_id) { + /* fprintf(stderr, "Instead of dict %u, this perturbed blob wants dict %u.\n", stuff->dict_id, custom_dict_id); */ + custom_ddict = readDictByID(stuff, custom_dict_id, &custom_dict, &custom_dict_size); + } ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); - ZSTD_DCtx_refDDict(dctx, NULL); + + if (custom_ddict != NULL) { + ZSTD_DCtx_refDDict(dctx, custom_ddict); + } else { + ZSTD_DCtx_refDDict(dctx, stuff->ddict); + } while (in.pos != in.size) { out.pos = 0; @@ -168,11 +308,20 @@ static int test_decompress(stuff_t* stuff) { fprintf( stderr, "Decompression failed: %s\n", ZSTD_getErrorName(ret)); */ + if (custom_ddict != NULL) { + ZSTD_freeDDict(custom_ddict); + free(custom_dict); + } return 0; } } stuff->success_count++; + + if (custom_ddict != NULL) { + ZSTD_freeDDict(custom_ddict); + free(custom_dict); + } return 1; } @@ -245,4 +394,4 @@ int main(int argc, char* argv[]) { free_stuff(&stuff); return 0; -} \ No newline at end of file +} From 5f468941848a661d6adaa6dc54da04b54e5c5ea1 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 5 Dec 2019 17:14:29 -0500 Subject: [PATCH 142/402] Fix playTests.sh Under QEMU --- tests/Makefile | 2 +- tests/playTests.sh | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 3917a7cf8ac..e50edbc83be 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -330,7 +330,7 @@ test-zstd-nolegacy: zstd-nolegacy test-zstd test-zstd32 test-zstd-nolegacy: datagen file $(ZSTD) - ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST) + EXE_PREFIX="$(QEMU_SYS)" ZSTD_BIN="$(ZSTD)" ./playTests.sh $(ZSTDRTTEST) test-gzstd: gzstd diff --git a/tests/playTests.sh b/tests/playTests.sh index 9e0d75d6c7d..d0943e1bbd2 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -102,9 +102,11 @@ case "$UNAME" in SunOS) DIFF="gdiff" ;; esac -println "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'" +println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN'" -[ -n "$ZSTD" ] || die "ZSTD variable must be defined!" +[ -n "$ZSTD_BIN" ] || die "ZSTD_BIN variable must be defined!" + +ZSTD="$EXE_PREFIX $ZSTD_BIN" if echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled' then @@ -493,19 +495,19 @@ cat hello.zstd world.zstd > helloworld.zstd $ZSTD -dc helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp println "testing zstdcat symlink" -ln -sf $ZSTD zstdcat -./zstdcat helloworld.zstd > result.tmp +ln -sf $ZSTD_BIN zstdcat +$EXE_PREFIX ./zstdcat helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp ln -s helloworld.zstd helloworld.link.zstd -./zstdcat helloworld.link.zstd > result.tmp +$EXE_PREFIX ./zstdcat helloworld.link.zstd > result.tmp $DIFF helloworld.tmp result.tmp rm zstdcat rm result.tmp println "testing zcat symlink" -ln -sf $ZSTD zcat -./zcat helloworld.zstd > result.tmp +ln -sf $ZSTD_BIN zcat +$EXE_PREFIX ./zcat helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp -./zcat helloworld.link.zstd > result.tmp +$EXE_PREFIX ./zcat helloworld.link.zstd > result.tmp $DIFF helloworld.tmp result.tmp rm zcat rm ./*.tmp ./*.zstd From 976c055a9ab12cda4b3d258ec6be376887070a6e Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 5 Dec 2019 17:14:57 -0500 Subject: [PATCH 143/402] Add Travis Test that Builds ARM on Trusty --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index a87c604aa83..297dcdd62bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -137,6 +137,13 @@ matrix: - make arminstall - make armfuzz + # Introduced to check compat with old toolchains, to prevent e.g. #1872 + - name: ARM Build Test (on Trusty) + dist: trusty + script: + - make arminstall + - make armbuild + - name: Qemu PPC + Fuzz Test # ~13mn dist: trusty # it seems ppc cross-compilation fails on "current" script: From 5af8cb7aea8d890b4801e50e5274371510f2cf33 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 4 Dec 2019 10:25:07 -0500 Subject: [PATCH 144/402] Use statbuf->st_mtim Again --- programs/util.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/programs/util.c b/programs/util.c index 0fc95512ea2..0751bf3ca2e 100644 --- a/programs/util.c +++ b/programs/util.c @@ -145,20 +145,20 @@ int UTIL_setFileStat(const char *filename, stat_t *statbuf) return -1; /* set access and modification times */ -#if defined(_WIN32) || (PLATFORM_POSIX_VERSION < 200809L) +#if (PLATFORM_POSIX_VERSION >= 200809L) && defined(st_mtime) + { + /* (atime, mtime) */ + struct timespec timebuf[2] = { {0, UTIME_NOW} }; + timebuf[1] = statbuf->st_mtim; + res += utimensat(AT_FDCWD, filename, timebuf, 0); + } +#else { struct utimbuf timebuf; timebuf.actime = time(NULL); timebuf.modtime = statbuf->st_mtime; res += utime(filename, &timebuf); } -#else - { - /* (atime, mtime) */ - struct timespec timebuf[2] = { {0, UTIME_NOW} }; - timebuf[1].tv_sec = statbuf->st_mtime; - res += utimensat(AT_FDCWD, filename, timebuf, 0); - } #endif #if !defined(_WIN32) From 5666835ea7e0bb3a3b7931d71484d6f7980c0404 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Wed, 4 Dec 2019 16:59:16 -0500 Subject: [PATCH 145/402] Add Comment --- programs/util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/programs/util.c b/programs/util.c index 0751bf3ca2e..51d848018a6 100644 --- a/programs/util.c +++ b/programs/util.c @@ -145,6 +145,10 @@ int UTIL_setFileStat(const char *filename, stat_t *statbuf) return -1; /* set access and modification times */ + /* We check that st_mtime is a macro here in order to give us confidence + * that struct stat has a struct timespec st_mtim member. We need this + * check because there are some platforms that claim to be POSIX 2008 + * compliant but which do not have st_mtim... */ #if (PLATFORM_POSIX_VERSION >= 200809L) && defined(st_mtime) { /* (atime, mtime) */ From e2a99db2dd151e951ad7f31cc94d2f9b8e08ddc0 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 5 Dec 2019 12:02:35 -0500 Subject: [PATCH 146/402] Also Define _ATFILE_SOURCE --- programs/platform.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/programs/platform.h b/programs/platform.h index 5934e59cf12..64ecd21fcdc 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -109,6 +109,15 @@ extern "C" { #endif /* PLATFORM_POSIX_VERSION */ +#if PLATFORM_POSIX_VERSION > 1 + /* glibc < 2.26 may not expose struct timespec def without this. + * See issue #1920. */ +# ifndef _ATFILE_SOURCE +# define _ATFILE_SOURCE +# endif +#endif + + /*-********************************************* * Detect if isatty() and fileno() are available ************************************************/ From 6f4341c43259031771d74fd06f7080aa85ac2ce2 Mon Sep 17 00:00:00 2001 From: Felix Handte Date: Thu, 26 Dec 2019 14:16:23 -0500 Subject: [PATCH 147/402] Fix playTests.sh Under QEMU (#1923) --- tests/Makefile | 2 +- tests/playTests.sh | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 3917a7cf8ac..e50edbc83be 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -330,7 +330,7 @@ test-zstd-nolegacy: zstd-nolegacy test-zstd test-zstd32 test-zstd-nolegacy: datagen file $(ZSTD) - ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST) + EXE_PREFIX="$(QEMU_SYS)" ZSTD_BIN="$(ZSTD)" ./playTests.sh $(ZSTDRTTEST) test-gzstd: gzstd diff --git a/tests/playTests.sh b/tests/playTests.sh index 9e0d75d6c7d..d0943e1bbd2 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -102,9 +102,11 @@ case "$UNAME" in SunOS) DIFF="gdiff" ;; esac -println "\nStarting playTests.sh isWindows=$isWindows ZSTD='$ZSTD'" +println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN'" -[ -n "$ZSTD" ] || die "ZSTD variable must be defined!" +[ -n "$ZSTD_BIN" ] || die "ZSTD_BIN variable must be defined!" + +ZSTD="$EXE_PREFIX $ZSTD_BIN" if echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled' then @@ -493,19 +495,19 @@ cat hello.zstd world.zstd > helloworld.zstd $ZSTD -dc helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp println "testing zstdcat symlink" -ln -sf $ZSTD zstdcat -./zstdcat helloworld.zstd > result.tmp +ln -sf $ZSTD_BIN zstdcat +$EXE_PREFIX ./zstdcat helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp ln -s helloworld.zstd helloworld.link.zstd -./zstdcat helloworld.link.zstd > result.tmp +$EXE_PREFIX ./zstdcat helloworld.link.zstd > result.tmp $DIFF helloworld.tmp result.tmp rm zstdcat rm result.tmp println "testing zcat symlink" -ln -sf $ZSTD zcat -./zcat helloworld.zstd > result.tmp +ln -sf $ZSTD_BIN zcat +$EXE_PREFIX ./zcat helloworld.zstd > result.tmp $DIFF helloworld.tmp result.tmp -./zcat helloworld.link.zstd > result.tmp +$EXE_PREFIX ./zcat helloworld.link.zstd > result.tmp $DIFF helloworld.tmp result.tmp rm zcat rm ./*.tmp ./*.zstd From ef1684f29a1757596147856294be90d274546f42 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Jan 2020 16:36:47 -0800 Subject: [PATCH 148/402] [doc] Adding -M# decompression operation modifier documentation (#1938) * Adding -M# operation modifier documentation * Adding long name, typo and update desc --- programs/zstd.1.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 6a63e978fae..22a76c239e2 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -122,6 +122,11 @@ the last one takes effect. Note: If `windowLog` is set to larger than 27, `--long=windowLog` or `--memory=windowSize` needs to be passed to the decompressor. +* `-M#`, `--memory=#`: + Set a memory usage limit for decompression. By default, Zstandard uses 128 MB + as the maximum amount of memory the decompressor is allowed to use, but you can + override this manually if need be in either direction (ie. you can increase or + decrease it). * `-T#`, `--threads=#`: Compress using `#` working threads (default: 1). If `#` is 0, attempt to detect and use the number of physical CPU cores. From b1f53b1a101af594fe69279c819fab9a50c4ce04 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Jan 2020 16:53:51 -0800 Subject: [PATCH 149/402] [fuzz] Dividing by targetCBlockSize instead of blockSize for nbBlocks fit (#1936) * Adding fail logging for superblock flow * Dividing by targetCBlockSize instead of blockSize * Adding new const and using more acurate formula for nbBlocks * Only do dstCapacity check if using superblock * Remvoing disabling logic * Updating test to make it catch more extreme case of previou bug * Also updating comment * Only taking compressEnd shortcut on non-superblock --- lib/common/zstd_internal.h | 2 ++ lib/compress/zstd_compress.c | 15 ++++++--------- tests/fuzzer.c | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index dcdcbdb81cd..0bb67783f53 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -128,6 +128,8 @@ static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; +#define ZSTD_FRAMECHECKSUMSIZE 4 + #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a674cea4022..a32fd34e4ad 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2462,6 +2462,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, const void* src, size_t srcSize, const size_t bss, U32 lastBlock) { + DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()"); /* Attempt superblock compression and return early if successful */ if (bss == ZSTDbss_compress) { size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); @@ -2472,6 +2473,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, } } + DEBUGLOG(6, "Attempting ZSTD_noCompressSuperBlock()"); /* Superblock compression failed, attempt to emit noCompress superblocks * and return early if that is successful and we have enough room for checksum */ { @@ -2480,6 +2482,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, return cSize; } + DEBUGLOG(6, "Attempting ZSTD_compressSequences() on superblock"); /* noCompress superblock emission failed. Attempt to compress normally * and return early if that is successful */ { @@ -2496,6 +2499,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, } } + DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock() on superblock"); /* Everything failed. Just emit a regular noCompress block */ return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); } @@ -2563,13 +2567,6 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, BYTE* op = ostart; U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; - /* This bool is set if there is enough room to output all noCompress superblocks. - * Just checks if the number of compressed blocks we can fit in dstCapacity is - * greater than the optimistic number of blocks we still have remaining. - * This might be UNset when data is uncompressable and we're streaming. */ - - const int enoughDstCapacityForNoCompressSuperBlocks = - (dstCapacity / (blockSize + 7 /* header + checksum */)) > (srcSize / blockSize); assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); @@ -2593,8 +2590,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; { size_t cSize; - int useTargetCBlockSize = ZSTD_useTargetCBlockSize(&cctx->appliedParams); - if (useTargetCBlockSize && enoughDstCapacityForNoCompressSuperBlocks) { + if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) { cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cSize); } else { @@ -3800,6 +3796,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_load: if ( (flushMode == ZSTD_e_end) + && !ZSTD_useTargetCBlockSize(&zcs->appliedParams) && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ && (zcs->inBuffPos == 0) ) { /* shortcut to compression pass directly into output buffer */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 337455d9f71..29d145d6337 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -501,14 +501,14 @@ static int basicUnitTests(U32 const seed, double compressibility) const size_t streamCompressThreshold = 161792; const size_t streamCompressDelta = 1024; - /* The first 1/3 of the buffer is compressible and the last 2/3 is + /* The first 1/5 of the buffer is compressible and the last 4/5 is * uncompressible. This is an approximation of the type of data * the fuzzer generated to catch this bug. Streams like this were making * zstd generate noCompress superblocks (which are larger than the src * they come from). Do this enough times, and we'll run out of room * and throw a dstSize_tooSmall error. */ - const size_t compressiblePartSize = srcSize/3; + const size_t compressiblePartSize = srcSize/5; const size_t uncompressiblePartSize = srcSize-compressiblePartSize; RDG_genBuffer(CNBuffer, compressiblePartSize, 0.5, 0.5, seed); RDG_genBuffer((BYTE*)CNBuffer+compressiblePartSize, uncompressiblePartSize, 0, 0, seed); From eb76f786bcffefd823f882bff95ade5c325042f9 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 6 Jan 2020 14:19:11 -0800 Subject: [PATCH 150/402] [bench] Automated benchmarking script (#1906) * Initial revised automated benchmarking script * Updating nb_iterations and making loop infinite * Allowing benchmarking params to be changed from cli * Renaming old speed test * Removing numpy dependency for cli * Change filename and benchmakr on pr level * Moving build outside loop and adding iterations param * Moving benchmarking to seperate travis ci test * Fixing typo and using unused variable * Added mode labels and updated README accordingly * Adding new mode 'current' that compraes facebook:dev against current hash * Typo * Reverting previous accidental diff * Typo * Adding frequency config variable to prevent github from blacklisting * Added new argument for frequency of fetching new prs * Updating documentation --- .travis.yml | 6 +- Makefile | 7 + ...speed.py => DEPRECATED-test-zstd-speed.py} | 1 + tests/Makefile | 3 + tests/README.md | 31 +++ tests/automated_benchmarking.py | 239 ++++++++++++++++++ 6 files changed, 286 insertions(+), 1 deletion(-) rename tests/{test-zstd-speed.py => DEPRECATED-test-zstd-speed.py} (99%) create mode 100644 tests/automated_benchmarking.py diff --git a/.travis.yml b/.travis.yml index 297dcdd62bc..b2fbcef1122 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,11 @@ matrix: script: - make check - - name: make test (complete) # ~14mn + - name: make benchmarking + script: + - make benchmarking + + - name: make test (complete) script: # DEVNULLRIGHTS : will request sudo rights to test permissions on /dev/null - DEVNULLRIGHTS=test make test diff --git a/Makefile b/Makefile index 8ff9642f1cc..7a7afca83cd 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,13 @@ shortest: .PHONY: check check: shortest +.PHONY: automated_benchmarking +automated_benchmarking: + $(MAKE) -C $(TESTDIR) $@ + +.PHONY: benchmarking +benchmarking: automated_benchmarking + ## examples: build all examples in `/examples` directory .PHONY: examples examples: lib diff --git a/tests/test-zstd-speed.py b/tests/DEPRECATED-test-zstd-speed.py similarity index 99% rename from tests/test-zstd-speed.py rename to tests/DEPRECATED-test-zstd-speed.py index 1096d5e4e22..1f6c8a7cde9 100755 --- a/tests/test-zstd-speed.py +++ b/tests/DEPRECATED-test-zstd-speed.py @@ -1,4 +1,5 @@ #! /usr/bin/env python3 +# THIS BENCHMARK IS BEING REPLACED BY automated-bencmarking.py # ################################################################ # Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. diff --git a/tests/Makefile b/tests/Makefile index e50edbc83be..81374110358 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -237,6 +237,9 @@ poolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(ZSTDDIR)/common/po versionsTest: clean $(PYTHON) test-zstd-versions.py +automated_benchmarking: clean + $(PYTHON) automated_benchmarking.py golden-compression 1 current 1 "" 60 + checkTag: checkTag.c $(ZSTDDIR)/zstd.h $(CC) $(FLAGS) $< -o $@$(EXT) diff --git a/tests/README.md b/tests/README.md index f3450119747..05df82e540a 100644 --- a/tests/README.md +++ b/tests/README.md @@ -20,9 +20,40 @@ This script creates `versionsTest` directory to which zstd repository is cloned. Then all tagged (released) versions of zstd are compiled. In the following step interoperability between zstd versions is checked. +#### `automated-benchmarking.py` - script for benchmarking zstd prs to dev + +This script benchmarks facebook:dev and changes from pull requests made to zstd and compares +them against facebook:dev to detect regressions. This script currently runs on a dedicated +desktop machine for every pull request that is made to the zstd repo but can also +be run on any machine via the command line interface. + +There are three modes of usage for this script: fastmode will just run a minimal single +build comparison (between facebook:dev and facebook:master), onetime will pull all the current +pull requests from the zstd repo and compare facebook:dev to all of them once, continuous +will continuously get pull requests from the zstd repo and run benchmarks against facebook:dev. + +``` +Example usage: python automated_benchmarking.py golden-compression 1 current 1 "" 60 +``` + +``` +usage: automated_benchmarking.py [-h] directory levels mode emails + +positional arguments: + directory directory with files to benchmark + levels levels to test eg ('1,2,3') + mode 'fastmode', 'onetime', 'current' or 'continuous' + iterations number of benchmark iterations to run + emails email addresses of people who will be alerted upon regression. + Only for continuous mode + frequency specifies the number of seconds to wait before each successive + check for new PRs in continuous mode +``` #### `test-zstd-speed.py` - script for testing zstd speed difference between commits +DEPRECATED + This script creates `speedTest` directory to which zstd repository is cloned. Then it compiles all branches of zstd and performs a speed benchmark for a given list of files (the `testFileNames` parameter). After `sleepTime` (an optional parameter, default 300 seconds) seconds the script checks repository for new commits. diff --git a/tests/automated_benchmarking.py b/tests/automated_benchmarking.py new file mode 100644 index 00000000000..a385c21b098 --- /dev/null +++ b/tests/automated_benchmarking.py @@ -0,0 +1,239 @@ +import argparse +import glob +import json +import os +import time +import pickle as pk +import subprocess +import urllib.request + + +GITHUB_API_PR_URL = "https://api.github.com/repos/facebook/zstd/pulls?state=open" +GITHUB_URL_TEMPLATE = "https://github.com/{}/zstd" +MASTER_BUILD = {"user": "facebook", "branch": "dev", "hash": None} + +# check to see if there are any new PRs every minute +DEFAULT_MAX_API_CALL_FREQUENCY_SEC = 60 +PREVIOUS_PRS_FILENAME = "prev_prs.pk" + +# Not sure what the threshold for triggering alarms should be +# 1% regression sounds like a little too sensitive but the desktop +# that I'm running it on is pretty stable so I think this is fine +CSPEED_REGRESSION_TOLERANCE = 0.01 +DSPEED_REGRESSION_TOLERANCE = 0.01 + + +def get_new_open_pr_builds(prev_state=True): + prev_prs = None + if os.path.exists(PREVIOUS_PRS_FILENAME): + with open(PREVIOUS_PRS_FILENAME, "rb") as f: + prev_prs = pk.load(f) + data = json.loads(urllib.request.urlopen(GITHUB_API_PR_URL).read().decode("utf-8")) + prs = { + d["url"]: { + "user": d["user"]["login"], + "branch": d["head"]["ref"], + "hash": d["head"]["sha"].strip(), + } + for d in data + } + with open(PREVIOUS_PRS_FILENAME, "wb") as f: + pk.dump(prs, f) + if not prev_state or prev_prs == None: + return list(prs.values()) + return [pr for url, pr in prs.items() if url not in prev_prs or prev_prs[url] != pr] + + +def get_latest_hashes(): + tmp = subprocess.run(["git", "log", "-1"], stdout=subprocess.PIPE).stdout.decode( + "utf-8" + ) + sha1 = tmp.split("\n")[0].split(" ")[1] + tmp = subprocess.run( + ["git", "show", "{}^1".format(sha1)], stdout=subprocess.PIPE + ).stdout.decode("utf-8") + sha2 = tmp.split("\n")[0].split(" ")[1] + tmp = subprocess.run( + ["git", "show", "{}^2".format(sha1)], stdout=subprocess.PIPE + ).stdout.decode("utf-8") + sha3 = "" if len(tmp) == 0 else tmp.split("\n")[0].split(" ")[1] + return [sha1.strip(), sha2.strip(), sha3.strip()] + + +def get_builds_for_latest_hash(): + hashes = get_latest_hashes() + for b in get_new_open_pr_builds(False): + if b["hash"] in hashes: + return [b] + return [] + + +def clone_and_build(build): + if build["user"] != None: + github_url = GITHUB_URL_TEMPLATE.format(build["user"]) + os.system( + """ + rm -rf zstd-{user}-{sha} && + git clone {github_url} zstd-{user}-{sha} && + cd zstd-{user}-{sha} && + {checkout_command} + make && + cd ../ + """.format( + user=build["user"], + github_url=github_url, + sha=build["hash"], + checkout_command="git checkout {} &&".format(build["hash"]) + if build["hash"] != None + else "", + ) + ) + return "zstd-{user}-{sha}/zstd".format(user=build["user"], sha=build["hash"]) + else: + os.system("cd ../ && make && cd tests") + return "../zstd" + + +def benchmark_single(executable, level, filename): + tmp = ( + subprocess.run( + [executable, "-qb{}".format(level), filename], stderr=subprocess.PIPE + ) + .stderr.decode("utf-8") + .split(" ") + ) + idx = [i for i, d in enumerate(tmp) if d == "MB/s"] + return [float(tmp[idx[0] - 1]), float(tmp[idx[1] - 1])] + + +def benchmark_n(executable, level, filename, n): + speeds_arr = [benchmark_single(executable, level, filename) for _ in range(n)] + cspeed, dspeed = max(b[0] for b in speeds_arr), max(b[1] for b in speeds_arr) + print( + "Bench (executable={} level={} filename={}, iterations={}):\n\t[cspeed: {} MB/s, dspeed: {} MB/s]".format( + os.path.basename(executable), + level, + os.path.basename(filename), + n, + cspeed, + dspeed, + ) + ) + return (cspeed, dspeed) + + +def benchmark(build, filenames, levels, iterations): + executable = clone_and_build(build) + return [ + [benchmark_n(executable, l, f, iterations) for f in filenames] for l in levels + ] + + +def get_regressions(baseline_build, test_build, iterations, filenames, levels): + old = benchmark(baseline_build, filenames, levels, iterations) + new = benchmark(test_build, filenames, levels, iterations) + regressions = [] + for j, level in enumerate(levels): + for k, filename in enumerate(filenames): + old_cspeed, old_dspeed = old[j][k] + new_cspeed, new_dspeed = new[j][k] + cspeed_reg = (old_cspeed - new_cspeed) / old_cspeed + dspeed_reg = (old_dspeed - new_dspeed) / old_dspeed + baseline_label = "{}:{} ({})".format( + baseline_build["user"], baseline_build["branch"], baseline_build["hash"] + ) + test_label = "{}:{} ({})".format( + test_build["user"], test_build["branch"], test_build["hash"] + ) + if cspeed_reg > CSPEED_REGRESSION_TOLERANCE: + regressions.append( + "[COMPRESSION REGRESSION] (level={} filename={})\n\t{} -> {}\n\t{} -> {} ({:0.2f}%)".format( + level, + filename, + baseline_label, + test_label, + old_cspeed, + new_cspeed, + cspeed_reg * 100.0, + ) + ) + if dspeed_reg > DSPEED_REGRESSION_TOLERANCE: + regressions.append( + "[DECOMPRESSION REGRESSION] (level={} filename={})\n\t{} -> {}\n\t{} -> {} ({:0.2f}%)".format( + level, + filename, + baseline_label, + test_label, + old_dspeed, + new_dspeed, + dspeed_reg * 100.0, + ) + ) + return regressions + +def main(filenames, levels, iterations, builds=None, emails=None, continuous=False, frequency=DEFAULT_MAX_API_CALL_FREQUENCY_SEC): + if builds == None: + builds = get_new_open_pr_builds() + while True: + for test_build in builds: + regressions = get_regressions( + MASTER_BUILD, test_build, iterations, filenames, levels + ) + body = "\n".join(regressions) + if len(regressions) > 0: + if emails != None: + os.system( + """ + echo "{}" | mutt -s "[zstd regression] caused by new pr" {} + """.format( + body, emails + ) + ) + print("Emails sent to {}".format(emails)) + print(body) + if not continuous: + break + time.sleep(frequency) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "directory", help="directory with files to benchmark", default="fuzz" + ) + parser.add_argument("levels", help="levels to test eg ('1,2,3')", default="1,2,3") + parser.add_argument( + "mode", help="'fastmode', 'onetime', 'current' or 'continuous'", default="onetime" + ) + parser.add_argument( + "iterations", help="number of benchmark iterations to run", default=5 + ) + parser.add_argument( + "emails", + help="email addresses of people who will be alerted upon regression. Only for continuous mode", + default=None, + ) + parser.add_argument( + "frequency", + help="specifies the number of seconds to wait before each successive check for new PRs in continuous mode", + default=DEFAULT_MAX_API_CALL_FREQUENCY_SEC + ) + + args = parser.parse_args() + filenames = glob.glob("{}/**".format(args.directory)) + levels = [int(l) for l in args.levels.split(",")] + mode = args.mode + iterations = int(args.iterations) + emails = args.emails + frequency = int(args.frequency) + + if mode == "onetime": + main(filenames, levels, iterations, frequency=frequency) + elif mode == "current": + builds = [{"user": None, "branch": "None", "hash": None}] + main(filenames, levels, iterations, builds, frequency=frequency) + elif mode == "fastmode": + builds = [{"user": "facebook", "branch": "master", "hash": None}] + main(filenames, levels, iterations, builds, frequency=frequency) + else: + main(filenames, levels, iterations, None, emails, True, frequency=frequency) From 311925626790268316dceae8f328d012baabd874 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 7 Jan 2020 09:51:22 -0800 Subject: [PATCH 151/402] updated CHANGELOG one missing item in v1.4.4 --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 588e34f9382..75043cb0a72 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,7 +21,8 @@ cli: commands --stream-size=# and --size-hint=#, by @nmagerko cli: command --exclude-compressed, by @shashank0791 cli: faster `-t` test mode cli: improved some error messages, by @vangyzen -cli: rare deadlock condition within dictionary builder, by @terrelln +cli: fix command `-D dictionary` on Windows, reported by @artyompetrov +cli: fix rare deadlock condition within dictionary builder, by @terrelln build: single-file decoder with emscripten compilation script, by @cwoffenden build: fixed zlibWrapper compilation on Visual Studio, reported by @bluenlive build: fixed deprecation warning for certain gcc version, reported by @jasonma163 From d0dcaf56c23d5691625b0b02ff106f08baa79f9c Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Wed, 8 Jan 2020 00:48:26 +0100 Subject: [PATCH 152/402] Make UTIL_countPhysicalCores() work under Cygwin (#1941) Cygwin currently uses the fallback implementation which just returns 1 every time, which leads to bad performance when zstd is called with -T0 for example. Instead use the POSIX implementation used for the BSDs which works just fine under Cygwin. Tested under Cygwin and MSYS2. --- programs/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 51d848018a6..399507c2aab 100644 --- a/programs/util.c +++ b/programs/util.c @@ -903,7 +903,7 @@ int UTIL_countPhysicalCores(void) return numPhysicalCores; } -#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) /* Use POSIX sysconf * see: man 3 sysconf */ From b77ad810c9bd7b33be22ff5e4d317d275496603c Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 8 Jan 2020 13:20:56 -0800 Subject: [PATCH 153/402] [fuzz] Fix regression_driver.c with directory input (#1944) The `numFiles` variable wasn't updated, so the fuzzer didn't do anything. I did two things to fix this: 1. Remove the `numFiles` variable entirely. 2. Error if we can't open a file and print the number of files tested. --- tests/fuzz/regression_driver.c | 35 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/tests/fuzz/regression_driver.c b/tests/fuzz/regression_driver.c index e875cf6ea9c..b3c5fba68e1 100644 --- a/tests/fuzz/regression_driver.c +++ b/tests/fuzz/regression_driver.c @@ -20,23 +20,28 @@ int main(int argc, char const **argv) { int const kFollowLinks = 1; FileNamesTable* files; const char** const fnTable = argv + 1; - unsigned numFiles = (unsigned)(argc - 1); uint8_t *buffer = NULL; size_t bufferSize = 0; unsigned i; - int ret; + unsigned numFilesTested = 0; + int ret = 0; + { + unsigned const numFiles = (unsigned)(argc - 1); #ifdef UTIL_HAS_CREATEFILELIST - files = UTIL_createExpandedFNT(fnTable, numFiles, kFollowLinks); - if (!files) numFiles = 0; + files = UTIL_createExpandedFNT(fnTable, numFiles, kFollowLinks); #else - files = UTIL_createFNT_fromROTable(fnTable, numFiles); - if (!files) numFiles = 0; - assert(numFiles == files->tableSize); + files = UTIL_createFNT_fromROTable(fnTable, numFiles); + assert(numFiles == files->tableSize); #endif - if (numFiles == 0) + } + if (!files) { + fprintf(stderr, "ERROR: Failed to create file names table\n"); + return 1; + } + if (files->tableSize == 0) fprintf(stderr, "WARNING: No files passed to %s\n", argv[0]); - for (i = 0; i < numFiles; ++i) { + for (i = 0; i < files->tableSize; ++i) { char const *fileName = files->fileNames[i]; DEBUGLOG(3, "Running %s", fileName); size_t const fileSize = UTIL_getFileSize(fileName); @@ -45,9 +50,10 @@ int main(int argc, char const **argv) { /* Check that it is a regular file, and that the fileSize is valid. * If it is not a regular file, then it may have been deleted since we - * constructed the list, so just skip it. + * constructed the list, so just skip it, but return an error exit code. */ if (!UTIL_isRegularFile(fileName)) { + ret = 1; continue; } FUZZ_ASSERT_MSG(fileSize <= kMaxFileSize, fileName); @@ -68,9 +74,14 @@ int main(int argc, char const **argv) { fclose(file); /* Run the fuzz target */ LLVMFuzzerTestOneInput(buffer, fileSize); + ++numFilesTested; + } + fprintf(stderr, "Tested %u files: ", numFilesTested); + if (ret == 0) { + fprintf(stderr, "Success!\n"); + } else { + fprintf(stderr, "Failure!\n"); } - - ret = 0; free(buffer); UTIL_freeFileNamesTable(files); return ret; From 03ffda7b88da5a37c9c31478494b8768da50a008 Mon Sep 17 00:00:00 2001 From: Igor Sugak Date: Wed, 8 Jan 2020 16:17:42 -0800 Subject: [PATCH 154/402] fix UBSAN's invalid-null-argument error in zstd_decompress.c (#1939) --- lib/decompress/zstd_decompress.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index d4d42e79447..9e6ab216dc9 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1482,7 +1482,9 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { size_t const length = MIN(dstCapacity, srcSize); - memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } From d1cc9d279704057c08ab976618c8bd629bc18f7e Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 9 Jan 2020 11:38:50 -0800 Subject: [PATCH 155/402] [fuzz] Allow zero sized buffers for streaming fuzzers (#1945) * Allow zero sized buffers in `stream_decompress`. Ensure that we never have two zero sized buffers in a row so we guarantee forwards progress. * Make case 4 in `stream_round_trip` do a zero sized buffers call followed by a full call to guarantee forwards progress. * Fix `limitCopy()` in legacy decoders. * Fix memcpy in `zstdmt_compress.c`. Catches the bug fixed in PR #1939 --- lib/compress/zstdmt_compress.c | 8 +++++--- lib/legacy/zstd_v04.c | 4 +++- lib/legacy/zstd_v05.c | 4 +++- lib/legacy/zstd_v06.c | 4 +++- lib/legacy/zstd_v07.c | 4 +++- tests/fuzz/stream_decompress.c | 27 +++++++++++++++++++++------ tests/fuzz/stream_round_trip.c | 7 +++++++ 7 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index d0542562976..4eaa3fcddea 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1714,9 +1714,11 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u assert(mtctx->doneJobID < mtctx->nextJobID); assert(cSize >= mtctx->jobs[wJobID].dstFlushed); assert(mtctx->jobs[wJobID].dstBuff.start != NULL); - memcpy((char*)output->dst + output->pos, - (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed, - toFlush); + if (toFlush > 0) { + memcpy((char*)output->dst + output->pos, + (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed, + toFlush); + } output->pos += toFlush; mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */ diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index 4dec308168e..0150c9fb482 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -3407,7 +3407,9 @@ static size_t ZBUFF_decompressWithDictionary(ZBUFF_DCtx* zbc, const void* src, s static size_t ZBUFF_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { size_t length = MIN(maxDstSize, srcSize); - memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 570e0ff86ee..aa564b415b9 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -3791,7 +3791,9 @@ static size_t ZBUFFv05_blockHeaderSize = 3; static size_t ZBUFFv05_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { size_t length = MIN(maxDstSize, srcSize); - memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 2a08e8dee84..d5d778fce14 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -4000,7 +4000,9 @@ size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* zbd) MEM_STATIC size_t ZBUFFv06_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { size_t length = MIN(dstCapacity, srcSize); - memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index a2eeff808e0..14a93655e19 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -4378,7 +4378,9 @@ size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd) MEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { size_t const length = MIN(dstCapacity, srcSize); - memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } diff --git a/tests/fuzz/stream_decompress.c b/tests/fuzz/stream_decompress.c index c71cc9d3ec6..aff9fcec785 100644 --- a/tests/fuzz/stream_decompress.c +++ b/tests/fuzz/stream_decompress.c @@ -27,27 +27,36 @@ static ZSTD_DStream *dstream = NULL; static void* buf = NULL; uint32_t seed; -static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer) +static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer, uint32_t min) { ZSTD_outBuffer buffer = { buf, 0, 0 }; - buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, kBufSize)); + buffer.size = (FUZZ_dataProducer_uint32Range(producer, min, kBufSize)); FUZZ_ASSERT(buffer.size <= kBufSize); + if (buffer.size == 0) { + buffer.dst = NULL; + } + return buffer; } static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size, - FUZZ_dataProducer_t *producer) + FUZZ_dataProducer_t *producer, + uint32_t min) { ZSTD_inBuffer buffer = { *src, 0, 0 }; FUZZ_ASSERT(*size > 0); - buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size)); + buffer.size = (FUZZ_dataProducer_uint32Range(producer, min, *size)); FUZZ_ASSERT(buffer.size <= *size); *src += buffer.size; *size -= buffer.size; + if (buffer.size == 0) { + buffer.src = NULL; + } + return buffer; } @@ -56,6 +65,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) /* Give a random portion of src data to the producer, to use for parameter generation. The rest will be used for (de)compression */ FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); + /* Guarantee forward progress by refusing to generate 2 zero sized + * buffers in a row. */ + int prevInWasZero = 0; + int prevOutWasZero = 0; size = FUZZ_dataProducer_reserveDataPrefix(producer); /* Allocate all buffers and contexts if not already allocated */ @@ -72,9 +85,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) } while (size > 0) { - ZSTD_inBuffer in = makeInBuffer(&src, &size, producer); + ZSTD_inBuffer in = makeInBuffer(&src, &size, producer, prevInWasZero ? 1 : 0); + prevInWasZero = in.size == 0; while (in.pos != in.size) { - ZSTD_outBuffer out = makeOutBuffer(producer); + ZSTD_outBuffer out = makeOutBuffer(producer, prevOutWasZero ? 1 : 0); + prevOutWasZero = out.size == 0; size_t const rc = ZSTD_decompressStream(dstream, &out, &in); if (ZSTD_isError(rc)) goto error; } diff --git a/tests/fuzz/stream_round_trip.c b/tests/fuzz/stream_round_trip.c index 703b1171336..810ed05eb9f 100644 --- a/tests/fuzz/stream_round_trip.c +++ b/tests/fuzz/stream_round_trip.c @@ -96,6 +96,13 @@ static size_t compress(uint8_t *dst, size_t capacity, } break; } + case 4: { + ZSTD_inBuffer nullIn = { NULL, 0, 0 }; + ZSTD_outBuffer nullOut = { NULL, 0, 0 }; + size_t const ret = ZSTD_compressStream2(cctx, &nullOut, &nullIn, ZSTD_e_continue); + FUZZ_ZASSERT(ret); + } + /* fall-through */ default: { size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue); From f25a6e9f8f36375bce85bfefdf388c770057c27c Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 10 Jan 2020 14:25:24 -0800 Subject: [PATCH 156/402] Adding new cli endpoint --patch-from= (#1940) * Adding new cli endpoint --diff-from= * Appveyor conversion nit * Using bool set trick instead of direct set * Removing --diff-from and only leaving --diff-from=# * Throwing error when both dictFileName vars are set * Clean up syntax * Renaming diff-from to patch-from * Revering comma separated syntax clean up * Updating playtests with patch-from * Uncommenting accidentally commented * Updating remaining docs and var names to be patch-from instead of diff-from * Constifying * Using existing log2 function and removing newly created one * Argument order (moving prefs to end) * Using comma separated syntax * Moving to outside #ifndef --- programs/fileio.c | 71 +++++++++++++++++++++++++++++++--------------- programs/fileio.h | 1 + programs/zstd.1.md | 11 ++++++- programs/zstdcli.c | 29 +++++++++++++------ tests/playTests.sh | 8 ++++++ 5 files changed, 87 insertions(+), 33 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 8fc25d357d5..e08c7f3501f 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -77,6 +77,7 @@ #define FNSPACE 30 +#define PATCHFROM_WINDOWSIZE_EXTRA_BYTES 1 KB /*-************************************* * Macros @@ -321,6 +322,7 @@ struct FIO_prefs_s { int nbWorkers; int excludeCompressedFiles; + int patchFromMode; }; @@ -487,6 +489,10 @@ void FIO_setLdmHashRateLog(FIO_prefs_t* const prefs, int ldmHashRateLog) { prefs->ldmHashRateLog = ldmHashRateLog; } +void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value) +{ + prefs->patchFromMode = value != 0; +} /*-************************************* * Functions @@ -624,7 +630,7 @@ FIO_openDstFile(FIO_prefs_t* const prefs, * @return : loaded size * if fileName==NULL, returns 0 and a NULL pointer */ -static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName) +static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName, FIO_prefs_t* const prefs) { FILE* fileHandle; U64 fileSize; @@ -638,9 +644,12 @@ static size_t FIO_createDictBuffer(void** bufferPtr, const char* fileName) if (fileHandle==NULL) EXM_THROW(31, "%s: %s", fileName, strerror(errno)); fileSize = UTIL_getFileSize(fileName); - if (fileSize > DICTSIZE_MAX) { - EXM_THROW(32, "Dictionary file %s is too large (> %u MB)", - fileName, DICTSIZE_MAX >> 20); /* avoid extreme cases */ + { + size_t const dictSizeMax = prefs->patchFromMode ? prefs->memLimit : DICTSIZE_MAX; + if (fileSize > dictSizeMax) { + EXM_THROW(32, "Dictionary file %s is too large (> %u bytes)", + fileName, (unsigned)dictSizeMax); /* avoid extreme cases */ + } } *bufferPtr = malloc((size_t)fileSize); if (*bufferPtr==NULL) EXM_THROW(34, "%s", strerror(errno)); @@ -743,6 +752,20 @@ FIO_createFilename_fromOutDir(const char* path, const char* outDirName, const si return result; } +/* FIO_highbit64() : + * gives position of highest bit. + * note : only works for v > 0 ! + */ +static unsigned FIO_highbit64(unsigned long long v) +{ + unsigned count = 0; + assert(v != 0); + v >>= 1; + while (v) { v >>= 1; count++; } + return count; +} + + #ifndef ZSTD_NOCOMPRESS /* ********************************************************************** @@ -760,8 +783,8 @@ typedef struct { } cRess_t; static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, - const char* dictFileName, int cLevel, - ZSTD_compressionParameters comprParams) { + const char* dictFileName, const size_t maxSrcFileSize, + int cLevel, ZSTD_compressionParameters comprParams) { cRess_t ress; memset(&ress, 0, sizeof(ress)); @@ -779,7 +802,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, /* Advanced parameters, including dictionary */ { void* dictBuffer; - size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName); /* works with dictFileName==NULL */ + size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName, prefs); /* works with dictFileName==NULL */ if (dictFileName && (dictBuffer==NULL)) EXM_THROW(32, "allocation error : can't create dictBuffer"); ress.dictFileName = dictFileName; @@ -787,6 +810,10 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog) comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT; + if (prefs->patchFromMode) { + comprParams.windowLog = FIO_highbit64((unsigned long long)maxSrcFileSize + PATCHFROM_WINDOWSIZE_EXTRA_BYTES); + } + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) ); @@ -1515,7 +1542,7 @@ int FIO_compressFilename(FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName, const char* dictFileName, int compressionLevel, ZSTD_compressionParameters comprParams) { - cRess_t const ress = FIO_createCResources(prefs, dictFileName, compressionLevel, comprParams); + cRess_t const ress = FIO_createCResources(prefs, dictFileName, (size_t)UTIL_getFileSize(srcFileName), compressionLevel, comprParams); int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel); @@ -1563,6 +1590,15 @@ FIO_determineCompressedName(const char* srcFileName, const char* outDirName, con return dstFileNameBuffer; } +static size_t FIO_getLargestFileSize(const char** inFileNames, unsigned nbFiles) +{ + size_t i, fileSize, maxFileSize = 0; + for (i = 0; i < nbFiles; i++) { + fileSize = (size_t)UTIL_getFileSize(inFileNames[i]); + maxFileSize = fileSize > maxFileSize ? fileSize : maxFileSize; + } + return maxFileSize; +} /* FIO_compressMultipleFilenames() : * compress nbFiles files @@ -1578,7 +1614,9 @@ int FIO_compressMultipleFilenames(FIO_prefs_t* const prefs, ZSTD_compressionParameters comprParams) { int error = 0; - cRess_t ress = FIO_createCResources(prefs, dictFileName, compressionLevel, comprParams); + cRess_t ress = FIO_createCResources(prefs, dictFileName, + FIO_getLargestFileSize(inFileNamesTable, nbFiles), + compressionLevel, comprParams); /* init */ assert(outFileName != NULL || suffix != NULL); @@ -1648,7 +1686,7 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi /* dictionary */ { void* dictBuffer; - size_t const dictBufferSize = FIO_createDictBuffer(&dictBuffer, dictFileName); + size_t const dictBufferSize = FIO_createDictBuffer(&dictBuffer, dictFileName, prefs); CHECK( ZSTD_initDStream_usingDict(ress.dctx, dictBuffer, dictBufferSize) ); free(dictBuffer); } @@ -1793,19 +1831,6 @@ static int FIO_passThrough(const FIO_prefs_t* const prefs, return 0; } -/* FIO_highbit64() : - * gives position of highest bit. - * note : only works for v > 0 ! - */ -static unsigned FIO_highbit64(unsigned long long v) -{ - unsigned count = 0; - assert(v != 0); - v >>= 1; - while (v) { v >>= 1; count++; } - return count; -} - /* FIO_zstdErrorHelp() : * detailed error message when requested window size is too large */ static void diff --git a/programs/fileio.h b/programs/fileio.h index a7da089f67d..c592542e55a 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -94,6 +94,7 @@ void FIO_setLiteralCompressionMode( void FIO_setNoProgress(unsigned noProgress); void FIO_setNotificationLevel(int level); void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles); +void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value); /*-************************************* * Single File functions diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 22a76c239e2..8539deb9e77 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -122,11 +122,20 @@ the last one takes effect. Note: If `windowLog` is set to larger than 27, `--long=windowLog` or `--memory=windowSize` needs to be passed to the decompressor. +* `--patch-from=FILE`: + Specify the file to be used as a reference point for zstd's diff engine. + This is effectively dictionary compression with some convenient parameter + selection, namely that windowSize > srcSize. + + Note: cannot use both this and -D together * `-M#`, `--memory=#`: - Set a memory usage limit for decompression. By default, Zstandard uses 128 MB + Set a memory usage limit. By default, Zstandard uses 128 MB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (ie. you can increase or decrease it). + + This is also used during compression when using with --patch-from=. In this case, + this parameter overrides that maximum size allowed for a dictionary. (128 MB). * `-T#`, `--threads=#`: Compress using `#` working threads (default: 1). If `#` is 0, attempt to detect and use the number of physical CPU cores. diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b7de3d8ff18..a9755421974 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -597,6 +597,7 @@ int main(int const argCount, const char* argv[]) const char* outFileName = NULL; const char* outDirName = NULL; const char* dictFileName = NULL; + const char* patchFromDictFileName = NULL; const char* suffix = ZSTD_EXTENSION; unsigned maxDictSize = g_defaultMaxDictSize; unsigned dictID = 0; @@ -618,7 +619,7 @@ int main(int const argCount, const char* argv[]) /* init */ (void)recursive; (void)cLevelLast; /* not used when ZSTD_NOBENCH set */ - (void)memLimit; /* not used when ZSTD_NODECOMPRESS set */ + (void)memLimit; assert(argCount >= 1); if ((filenames==NULL) || (file_of_names==NULL)) { DISPLAY("zstd: allocation error \n"); exit(1); } programName = lastNameFromPath(programName); @@ -758,6 +759,7 @@ int main(int const argCount, const char* argv[]) if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--output-dir-flat=")) { outDirName = argument; continue; } + if (longCommandWArg(&argument, "--patch-from=")) { patchFromDictFileName = argument; continue; } if (longCommandWArg(&argument, "--long")) { unsigned ldmWindowLog = 0; ldmFlag = 1; @@ -868,7 +870,7 @@ int main(int const argCount, const char* argv[]) /* destination file name */ case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break; - /* limit decompression memory */ + /* limit memory */ case 'M': argument++; memLimit = readU32FromChar(&argument); @@ -1167,12 +1169,28 @@ int main(int const argCount, const char* argv[]) } } #endif + if (dictFileName != NULL && patchFromDictFileName != NULL) { + DISPLAY("error : can't use -D and --patch-from=# at the same time \n"); + CLEAN_RETURN(1); + } + /* No status message in pipe mode (stdin - stdout) or multi-files mode */ if (!strcmp(filenames->fileNames[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1; if ((filenames->tableSize > 1) & (g_displayLevel==2)) g_displayLevel=1; /* IO Stream/File */ FIO_setNotificationLevel(g_displayLevel); + FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL); + if (patchFromDictFileName != NULL) { + dictFileName = patchFromDictFileName; + } + if (memLimit == 0) { + if (compressionParams.windowLog == 0) { + memLimit = (U32)1 << g_defaultMaxWindowLog; + } else { + memLimit = (U32)1 << (compressionParams.windowLog & 31); + } } + FIO_setMemLimit(prefs, memLimit); if (operation==zom_compress) { #ifndef ZSTD_NOCOMPRESS FIO_setNbWorkers(prefs, nbWorkers); @@ -1204,13 +1222,6 @@ int main(int const argCount, const char* argv[]) #endif } else { /* decompression or test */ #ifndef ZSTD_NODECOMPRESS - if (memLimit == 0) { - if (compressionParams.windowLog == 0) { - memLimit = (U32)1 << g_defaultMaxWindowLog; - } else { - memLimit = (U32)1 << (compressionParams.windowLog & 31); - } } - FIO_setMemLimit(prefs, memLimit); if (filenames->tableSize == 1 && outFileName) { operationResult = FIO_decompressFilename(prefs, outFileName, filenames->fileNames[0], dictFileName); } else { diff --git a/tests/playTests.sh b/tests/playTests.sh index d0943e1bbd2..e0ca2da490f 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1202,6 +1202,14 @@ then $ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread" fi +println "\n===> patch-from tests" + +./datagen -g1000 -P50 > tmp_dict +./datagen -g1000 -P10 > tmp_patch +$ZSTD --memory=10000 --patch-from=tmp_dict tmp_patch -o tmp_patch_diff +$ZSTD -d --memory=10000 --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon +$DIFF -s tmp_patch_recon tmp_patch +rm -rf tmp_* println "\n===> large files tests " From ddd4c39736a0960ba466632cbf8cf76ceb2c59bc Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 11 Jan 2020 01:04:14 +0100 Subject: [PATCH 157/402] Fix the c99/cmake build under Cygwin/MSYS2 When building zst under cygwin or msys2 with std=c99 the build would fail because of an undefined fileno()/_fileno(), which is used by the IS_CONSOLE() macro. When building with -std=c99 (gcc otherwise defaults to gnu, which implies POSIX), which is the default of the cmake build, then including unistd.h wont define _POSIX_VERSION and all other headers also wont expose POSIX API. To fix this make sure to define _POSIX_C_SOURCE with the version we want before including unistd.h and so that _POSIX_VERSION is set to the version provided by the system. Since Cygwin/MSYS2 just follow POSIX we can also remove their special cases for defining IS_CONSOLE(). And, for completeness, also explicitly include stdio.h which is what actually declares fileno(). Tested with the normal make file and cmake under MSYS2 and Cygwin. --- programs/platform.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/platform.h b/programs/platform.h index 64ecd21fcdc..31820631eea 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -90,7 +90,7 @@ extern "C" { && ( defined(__unix__) || defined(__unix) \ || defined(__midipix__) || defined(__VMS) || defined(__HAIKU__) ) -# if defined(__linux__) || defined(__linux) +# if defined(__linux__) || defined(__linux) || defined(__CYGWIN__) # ifndef _POSIX_C_SOURCE # define _POSIX_C_SOURCE 200809L /* feature test macro : https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */ # endif @@ -123,11 +123,11 @@ extern "C" { ************************************************/ #if (defined(__linux__) && (PLATFORM_POSIX_VERSION > 1)) \ || (PLATFORM_POSIX_VERSION >= 200112L) \ - || defined(__DJGPP__) \ - || defined(__MSYS__) + || defined(__DJGPP__) # include /* isatty */ +# include /* fileno */ # define IS_CONSOLE(stdStream) isatty(fileno(stdStream)) -#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__) +#elif defined(MSDOS) || defined(OS2) # include /* _isatty */ # define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream)) #elif defined(WIN32) || defined(_WIN32) From 036b30b555e846dfccc435d781e402b4d38b3c8d Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 10 Jan 2020 18:02:11 -0800 Subject: [PATCH 158/402] Fix super block compression and stream raw blocks in decompression (#1947) Super blocks must never violate the zstd block bound of input_size + ZSTD_blockHeaderSize. The individual sub-blocks may, but not the super block. If the superblock violates the block bound we are liable to violate ZSTD_compressBound(), which we must not do. Whenever the super block violates the block bound we instead emit an uncompressed block. This means we increase the latency because of the single uncompressed block. I fix this by enabling streaming an uncompressed block, so the latency of an uncompressed block is 1 byte. This doesn't reduce the latency of the buffer-less API, but I don't think we really care. * I added a test case that verifies that the decompression has 1 byte latency. * I rely on existing zstreamtest / fuzzer / libfuzzer regression tests for correctness. During development I had several correctness bugs, and they easily caught them. * The added assert that the superblock doesn't violate the block bound will help us discover any missed conditions (though I think I got them all). Credit to OSS-Fuzz. --- lib/compress/zstd_compress.c | 87 ++++++++++++------------- lib/compress/zstd_compress_superblock.c | 26 +------- lib/compress/zstd_compress_superblock.h | 10 --- lib/decompress/zstd_decompress.c | 39 +++++++++-- tests/zstreamtest.c | 37 +++++++++++ 5 files changed, 113 insertions(+), 86 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a32fd34e4ad..e11092b41f5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -38,8 +38,8 @@ * Note that the result from this function is only compatible with the "normal" * full-block strategy. * When there are a lot of small blocks due to frequent flush in streaming mode - * or targetCBlockSize, the overhead of headers can make the compressed data to - * be larger than the return value of ZSTD_compressBound(). + * the overhead of headers can make the compressed data to be larger than the + * return value of ZSTD_compressBound(). */ size_t ZSTD_compressBound(size_t srcSize) { return ZSTD_COMPRESSBOUND(srcSize); @@ -2385,6 +2385,13 @@ static int ZSTD_isRLE(const BYTE *ip, size_t length) { return 1; } +static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) +{ + ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; + zc->blockState.prevCBlock = zc->blockState.nextCBlock; + zc->blockState.nextCBlock = tmp; +} + static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 frame) @@ -2435,10 +2442,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, out: if (!ZSTD_isError(cSize) && cSize > 1) { - /* confirm repcodes and entropy tables when emitting a compressed block */ - ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; - zc->blockState.prevCBlock = zc->blockState.nextCBlock; - zc->blockState.nextCBlock = tmp; + ZSTD_confirmRepcodesAndEntropyTables(zc); } /* We check that dictionaries have offset codes available for the first * block. After the first block, the offcode table might not have large @@ -2450,57 +2454,45 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, return cSize; } -static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) -{ - ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; - zc->blockState.prevCBlock = zc->blockState.nextCBlock; - zc->blockState.nextCBlock = tmp; -} - static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const size_t bss, U32 lastBlock) { DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()"); - /* Attempt superblock compression and return early if successful */ if (bss == ZSTDbss_compress) { + /* Attempt superblock compression. + * + * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the + * standard ZSTD_compressBound(). This is a problem, because even if we have + * space now, taking an extra byte now could cause us to run out of space later + * and violate ZSTD_compressBound(). + * + * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize. + * + * In order to respect ZSTD_compressBound() we must attempt to emit a raw + * uncompressed block in these cases: + * * cSize == 0: Return code for an uncompressed block. + * * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize). + * ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of + * output space. + * * cSize >= blockBound(srcSize): We have expanded the block too much so + * emit an uncompressed block. + */ size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); - FORWARD_IF_ERROR(cSize); - if (cSize != 0) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; - } - } - - DEBUGLOG(6, "Attempting ZSTD_noCompressSuperBlock()"); - /* Superblock compression failed, attempt to emit noCompress superblocks - * and return early if that is successful and we have enough room for checksum */ - { - size_t const cSize = ZSTD_noCompressSuperBlock(dst, dstCapacity, src, srcSize, zc->appliedParams.targetCBlockSize, lastBlock); - if (cSize != ERROR(dstSize_tooSmall) && (dstCapacity - cSize) >= 4) - return cSize; - } - - DEBUGLOG(6, "Attempting ZSTD_compressSequences() on superblock"); - /* noCompress superblock emission failed. Attempt to compress normally - * and return early if that is successful */ - { - size_t const cSize = ZSTD_compressSequences(&zc->seqStore, - &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, - &zc->appliedParams, (BYTE*)dst+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, - srcSize, zc->entropyWorkspace, HUF_WORKSPACE_SIZE, zc->bmi2); - FORWARD_IF_ERROR(cSize); - if (cSize != 0) { - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24((BYTE*)dst, cBlockHeader24); - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize + ZSTD_blockHeaderSize; + if (cSize != ERROR(dstSize_tooSmall)) { + FORWARD_IF_ERROR(cSize); + if (cSize != 0 && cSize < srcSize + ZSTD_blockHeaderSize) { + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; + } } } - DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock() on superblock"); - /* Everything failed. Just emit a regular noCompress block */ + DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()"); + /* Superblock compression failed, attempt to emit a single no compress block. + * The decoder will be able to stream this block since it is uncompressed. + */ return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); } @@ -2593,6 +2585,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) { cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); FORWARD_IF_ERROR(cSize); + assert(cSize > 0); + assert(cSize <= blockSize + ZSTD_blockHeaderSize); } else { cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, @@ -3796,7 +3790,6 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_load: if ( (flushMode == ZSTD_e_end) - && !ZSTD_useTargetCBlockSize(&zcs->appliedParams) && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ && (zcs->inBuffPos == 0) ) { /* shortcut to compression pass directly into output buffer */ diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index eb3e369d636..39af1aba710 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -658,7 +658,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, /* I think there is an optimization opportunity here. * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful * since it recalculates estimate from scratch. - * For example, it would recount literal distribution and symbol codes everytime. + * For example, it would recount literal distribution and symbol codes everytime. */ cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount, entropy, entropyMetadata, @@ -716,27 +716,3 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, zc->bmi2, lastBlock, zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */); } - -size_t ZSTD_noCompressSuperBlock(void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - size_t targetCBlockSize, - unsigned lastBlock) { - const BYTE* const istart = (const BYTE*)src; - const BYTE* const iend = istart + srcSize; - const BYTE* ip = istart; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstCapacity; - BYTE* op = ostart; - DEBUGLOG(5, "ZSTD_noCompressSuperBlock (dstCapacity=%zu, srcSize=%zu, targetCBlockSize=%zu)", - dstCapacity, srcSize, targetCBlockSize); - while (ip < iend) { - size_t remaining = iend-ip; - unsigned lastSubBlock = remaining <= targetCBlockSize; - size_t blockSize = lastSubBlock ? remaining : targetCBlockSize; - size_t cSize = ZSTD_noCompressBlock(op, oend-op, ip, blockSize, lastSubBlock && lastBlock); - FORWARD_IF_ERROR(cSize); - ip += blockSize; - op += cSize; - } - return op-ostart; -} diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h index b1d72ec4ed8..099ad3bb8f1 100644 --- a/lib/compress/zstd_compress_superblock.h +++ b/lib/compress/zstd_compress_superblock.h @@ -28,14 +28,4 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, unsigned lastBlock); -/* ZSTD_noCompressSuperBlock() : -* Used to break a super block into multiple uncompressed sub blocks -* when targetCBlockSize is being used. -* The given block will be broken into multiple uncompressed sub blocks that are -* around targetCBlockSize. */ -size_t ZSTD_noCompressSuperBlock(void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - size_t targetCBlockSize, - unsigned lastBlock); - #endif /* ZSTD_COMPRESS_ADVANCED_H */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 9e6ab216dc9..d92440ae8a2 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -845,6 +845,24 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr ****************************************/ size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; } +/** + * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed, + * we allow taking a partial block as the input. Currently only raw uncompressed blocks can + * be streamed. + * + * For blocks that can be streamed, this allows us to reduce the latency until we produce + * output, and avoid copying the input. + * + * @param inputSize - The total amount of input that the caller currently has. + */ +static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) { + if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock)) + return dctx->expected; + if (dctx->bType != bt_raw) + return dctx->expected; + return MIN(MAX(inputSize, 1), dctx->expected); +} + ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { switch(dctx->stage) { @@ -877,7 +895,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c { DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize); /* Sanity check */ - RETURN_ERROR_IF(srcSize != dctx->expected, srcSize_wrong, "not allowed"); + RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed"); if (dstCapacity) ZSTD_checkContinuity(dctx, dst); switch (dctx->stage) @@ -944,22 +962,34 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case bt_compressed: DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed"); rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1); + dctx->expected = 0; /* Streaming not supported */ break; case bt_raw : + assert(srcSize <= dctx->expected); rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); + FORWARD_IF_ERROR(rSize); + assert(rSize == srcSize); + dctx->expected -= rSize; break; case bt_rle : rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize); + dctx->expected = 0; /* Streaming not supported */ break; case bt_reserved : /* should never happen */ default: RETURN_ERROR(corruption_detected); } - if (ZSTD_isError(rSize)) return rSize; + FORWARD_IF_ERROR(rSize); RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum"); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); dctx->decodedSize += rSize; if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + dctx->previousDstEnd = (char*)dst + rSize; + + /* Stay on the same stage until we are finished streaming the block. */ + if (dctx->expected > 0) { + return rSize; + } if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize); @@ -977,7 +1007,6 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c } else { dctx->stage = ZSTDds_decodeBlockHeader; dctx->expected = ZSTD_blockHeaderSize; - dctx->previousDstEnd = (char*)dst + rSize; } return rSize; } @@ -1645,7 +1674,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB case zdss_read: DEBUGLOG(5, "stage zdss_read"); - { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds); + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip); DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize); if (neededInSize==0) { /* end of frame */ zds->streamStage = zdss_init; @@ -1673,6 +1702,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB size_t const toLoad = neededInSize - zds->inPos; int const isSkipFrame = ZSTD_isSkipFrame(zds); size_t loadedSize; + /* At this point we shouldn't be decompressing a block that we can stream. */ + assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip)); if (isSkipFrame) { loadedSize = MIN(toLoad, (size_t)(iend-ip)); } else { diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 549a4981bbb..890e66f9ecb 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1273,6 +1273,43 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : raw block can be streamed: ", testNb++); + { size_t const inputSize = 10000; + size_t const compCapacity = ZSTD_compressBound(inputSize); + BYTE* const input = (BYTE*)malloc(inputSize); + BYTE* const comp = (BYTE*)malloc(compCapacity); + BYTE* const decomp = (BYTE*)malloc(inputSize); + + CHECK(input == NULL || comp == NULL || decomp == NULL, "failed to alloc buffers"); + + RDG_genBuffer(input, inputSize, 0.0, 0.0, seed); + { size_t const compSize = ZSTD_compress(comp, compCapacity, input, inputSize, -(int)inputSize); + ZSTD_inBuffer in = { comp, 0, 0 }; + ZSTD_outBuffer out = { decomp, 0, 0 }; + CHECK_Z(compSize); + CHECK_Z( ZSTD_DCtx_reset(zd, ZSTD_reset_session_and_parameters) ); + while (in.size < compSize) { + in.size = MIN(in.size + 100, compSize); + while (in.pos < in.size) { + size_t const outPos = out.pos; + if (out.pos == out.size) { + out.size = MIN(out.size + 10, inputSize); + } + CHECK_Z( ZSTD_decompressStream(zd, &out, &in) ); + CHECK(!(out.pos > outPos), "We are not streaming (no output generated)"); + } + } + CHECK(in.pos != compSize, "Not all input consumed!"); + CHECK(out.pos != inputSize, "Not all output produced!"); + } + CHECK(memcmp(input, decomp, inputSize), "round trip failed!"); + + free(input); + free(comp); + free(decomp); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : dictionary + uncompressible block + reusing tables checks offset table validity: ", testNb++); { ZSTD_CDict* const cdict = ZSTD_createCDict_advanced( dictionary.start, dictionary.filled, From 9a5d8a6cb44970aa6cc33cd4e278bea347b6beee Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 11 Jan 2020 10:41:56 +0100 Subject: [PATCH 159/402] appveyor: build with CMake under Cygwin --- appveyor.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index dd2c02ac482..fb8ea3793ce 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -187,6 +187,9 @@ version: 1.0.{build} environment: matrix: + - COMPILER: "gcc" + HOST: "cygwin" + PLATFORM: "x64" - COMPILER: "gcc" HOST: "mingw" PLATFORM: "x64" @@ -220,6 +223,14 @@ install: - ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION% - SET PATH_ORIGINAL=%PATH% + - if [%HOST%]==[cygwin] ( + ECHO Installing Cygwin Packages && + C:\cygwin64\setup-x86_64.exe -qnNdO -R "C:\cygwin64" -g -P ^ + gcc-g++,^ + gcc,^ + cmake,^ + make + ) - if [%HOST%]==[mingw] ( SET "PATH_MINGW32=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin" && SET "PATH_MINGW64=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin" && @@ -232,6 +243,16 @@ build_script: - ECHO Building %COMPILER% %PLATFORM% %CONFIGURATION% + - if [%HOST%]==[cygwin] ( + set CHERE_INVOKING=yes && + set CC=%COMPILER% && + C:\cygwin64\bin\bash --login -c " + set -e; + cd build/cmake; + CFLAGS='-Werror' cmake -G 'Unix Makefiles' .; + make -j4; + " + ) - if [%HOST%]==[mingw] ( ( if [%PLATFORM%]==[x64] ( SET "PATH=%PATH_MINGW64%;%PATH_ORIGINAL%" From 3ed0f651581760827dc86df2fb15fea9e897a879 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 13 Jan 2020 11:52:33 -0800 Subject: [PATCH 160/402] [cmake] Add playTests.sh as a test --- .travis.yml | 2 +- Makefile | 8 +- appveyor.yml | 3 +- build/cmake/CMakeLists.txt | 3 + .../AddZstdCompilationFlags.cmake | 8 ++ build/cmake/tests/CMakeLists.txt | 4 + tests/Makefile | 2 +- tests/fuzzer.c | 1 + tests/playTests.sh | 118 +++++++++--------- 9 files changed, 86 insertions(+), 63 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2fbcef1122..8f7083c141a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,7 +84,7 @@ matrix: - make clean - make -j check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - - name: cmake build check # ~2mn + - name: cmake build and test check # ~2mn script: - make cmakebuild diff --git a/Makefile b/Makefile index 7a7afca83cd..9b19d4d31a8 100644 --- a/Makefile +++ b/Makefile @@ -344,7 +344,7 @@ endif ifneq (,$(filter MSYS%,$(shell uname))) HOST_OS = MSYS -CMAKE_PARAMS = -G"MSYS Makefiles" -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON +CMAKE_PARAMS = -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug -DZSTD_MULTITHREAD_SUPPORT:BOOL=OFF -DZSTD_BUILD_STATIC:BOOL=ON -DZSTD_BUILD_TESTS:BOOL=ON endif @@ -356,7 +356,11 @@ cmakebuild: cmake --version $(RM) -r $(BUILDIR)/cmake/build mkdir $(BUILDIR)/cmake/build - cd $(BUILDIR)/cmake/build ; cmake -DCMAKE_INSTALL_PREFIX:PATH=~/install_test_dir $(CMAKE_PARAMS) .. ; $(MAKE) install ; $(MAKE) uninstall + cd $(BUILDIR)/cmake/build; cmake -DCMAKE_INSTALL_PREFIX:PATH=~/install_test_dir $(CMAKE_PARAMS) .. + $(MAKE) -C $(BUILDIR)/cmake/build -j4; + $(MAKE) -C $(BUILDIR)/cmake/build install; + $(MAKE) -C $(BUILDIR)/cmake/build uninstall; + cd $(BUILDIR)/cmake/build; ctest -V c89build: clean $(CC) -v diff --git a/appveyor.yml b/appveyor.yml index fb8ea3793ce..b483a0b5d09 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -249,8 +249,9 @@ C:\cygwin64\bin\bash --login -c " set -e; cd build/cmake; - CFLAGS='-Werror' cmake -G 'Unix Makefiles' .; + CFLAGS='-Werror' cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON .; make -j4; + ctest -V; " ) - if [%HOST%]==[mingw] ( diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index 9d0e7fb0b5c..be5ce15186f 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -23,6 +23,8 @@ else() endif() cmake_policy(VERSION ${ZSTD_CMAKE_POLICY_VERSION}) +set(CMAKE_BUILD_WITH_INSTALL_RPATH on) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") set(ZSTD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..") set(LIBRARY_DIR ${ZSTD_SOURCE_DIR}/lib) @@ -137,6 +139,7 @@ if (ZSTD_BUILD_PROGRAMS) endif () if (ZSTD_BUILD_TESTS) + enable_testing() if (NOT ZSTD_BUILD_STATIC) message(SEND_ERROR "You need to build static library to build tests") endif () diff --git a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake index 6cdf2b3afb0..18681988513 100644 --- a/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake +++ b/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake @@ -33,6 +33,10 @@ macro(ADD_ZSTD_COMPILATION_FLAGS) EnableCompilerFlag("-Wcast-align" true true) EnableCompilerFlag("-Wcast-qual" true true) EnableCompilerFlag("-Wstrict-prototypes" true false) + # Enable asserts in Debug mode + if (CMAKE_BUILD_TYPE MATCHES "Debug") + EnableCompilerFlag("-DDEBUGLEVEL=1" true true) + endif () elseif (MSVC) # Add specific compilation flags for Windows Visual set(ACTIVATE_MULTITHREADED_COMPILATION "ON" CACHE BOOL "activate multi-threaded compilation (/MP flag)") @@ -43,6 +47,10 @@ macro(ADD_ZSTD_COMPILATION_FLAGS) # UNICODE SUPPORT EnableCompilerFlag("/D_UNICODE" true true) EnableCompilerFlag("/DUNICODE" true true) + # Enable asserts in Debug mode + if (CMAKE_BUILD_TYPE MATCHES "Debug") + EnableCompilerFlag("/DDEBUGLEVEL=1" true true) + endif () endif () # Remove duplicates compilation flags diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt index 063260a0ee5..10039fb96da 100644 --- a/build/cmake/tests/CMakeLists.txt +++ b/build/cmake/tests/CMakeLists.txt @@ -52,6 +52,10 @@ target_link_libraries(fuzzer libzstd_static) add_executable(zstreamtest ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/seqgen.c ${TESTS_DIR}/zstreamtest.c) target_link_libraries(zstreamtest libzstd_static) +add_test( + NAME playTests + COMMAND sh -c "ZSTD_BIN='$' DATAGEN_BIN='$' '${TESTS_DIR}/playTests.sh'") + if (UNIX) add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c) target_link_libraries(paramgrill libzstd_static m) #m is math library diff --git a/tests/Makefile b/tests/Makefile index 81374110358..241e3f2b412 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -333,7 +333,7 @@ test-zstd-nolegacy: zstd-nolegacy test-zstd test-zstd32 test-zstd-nolegacy: datagen file $(ZSTD) - EXE_PREFIX="$(QEMU_SYS)" ZSTD_BIN="$(ZSTD)" ./playTests.sh $(ZSTDRTTEST) + EXE_PREFIX="$(QEMU_SYS)" ZSTD_BIN="$(ZSTD)" DATAGEN_BIN=./datagen ./playTests.sh $(ZSTDRTTEST) test-gzstd: gzstd diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 29d145d6337..bad23d47909 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -25,6 +25,7 @@ #include /* free */ #include /* fgets, sscanf */ #include /* strcmp */ +#undef NDEBUG #include #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */ #include "fse.h" diff --git a/tests/playTests.sh b/tests/playTests.sh index e0ca2da490f..ffb455a8e15 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -22,9 +22,9 @@ roundTripTest() { fi rm -f tmp1 tmp2 - println "roundTripTest: ./datagen $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel" - ./datagen $1 $proba | $MD5SUM > tmp1 - ./datagen $1 $proba | $ZSTD --ultra -v$cLevel | $ZSTD -d$dLevel | $MD5SUM > tmp2 + println "roundTripTest: $DATAGEN $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel" + $DATAGEN $1 $proba | $MD5SUM > tmp1 + $DATAGEN $1 $proba | $ZSTD --ultra -v$cLevel | $ZSTD -d$dLevel | $MD5SUM > tmp2 $DIFF -q tmp1 tmp2 } @@ -43,8 +43,8 @@ fileRoundTripTest() { fi rm -f tmp.zstd tmp.md5.1 tmp.md5.2 - println "fileRoundTripTest: ./datagen $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d" - ./datagen $1 $local_p > tmp + println "fileRoundTripTest: $DATAGEN $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d" + $DATAGEN $1 $local_p > tmp < tmp $MD5SUM > tmp.md5.1 $ZSTD --ultra -v$local_c -c tmp | $ZSTD -d$local_d | $MD5SUM > tmp.md5.2 $DIFF -q tmp.md5.1 tmp.md5.2 @@ -105,8 +105,10 @@ esac println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN'" [ -n "$ZSTD_BIN" ] || die "ZSTD_BIN variable must be defined!" +[ -n "$DATAGEN_BIN" ] || die "DATAGEN_BIN variable must be defined!" ZSTD="$EXE_PREFIX $ZSTD_BIN" +DATAGEN="$DATAGEN_BIN" if echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled' then @@ -119,7 +121,7 @@ fi println "\n===> simple tests " -./datagen > tmp +$DATAGEN > tmp println "test : basic compression " $ZSTD -f tmp # trivial compression case, creates tmp.zst println "test : basic decompression" @@ -172,7 +174,7 @@ fi println "test : null-length file roundtrip" println -n '' | $ZSTD - --stdout | $ZSTD -d --stdout println "test : ensure small file doesn't add 3-bytes null block" -./datagen -g1 > tmp1 +$DATAGEN -g1 > tmp1 $ZSTD tmp1 -c | wc -c | grep "14" $ZSTD < tmp1 | wc -c | grep "14" println "test : decompress file with wrong suffix (must fail)" @@ -226,11 +228,11 @@ $ZSTD -b --fast=1 -i0e1 tmp --no-compress-literals println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir -./datagen $size > precompressedFilterTestDir/input.5 -./datagen $size > precompressedFilterTestDir/input.6 +$DATAGEN $size > precompressedFilterTestDir/input.5 +$DATAGEN $size > precompressedFilterTestDir/input.6 $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir -./datagen $size > precompressedFilterTestDir/input.7 -./datagen $size > precompressedFilterTestDir/input.8 +$DATAGEN $size > precompressedFilterTestDir/input.7 +$DATAGEN $size > precompressedFilterTestDir/input.8 $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir test ! -f precompressedFilterTestDir/input.5.zst.zst test ! -f precompressedFilterTestDir/input.6.zst.zst @@ -242,7 +244,7 @@ else println "Test is not successful" fi # File Extension check. -./datagen $size > precompressedFilterTestDir/input.zstbar +$DATAGEN $size > precompressedFilterTestDir/input.zstbar $ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir # ZSTD should compress input.zstbar test -f precompressedFilterTestDir/input.zstbar.zst @@ -318,9 +320,9 @@ if [ "$?" -eq 139 ]; then die "should not have segfaulted" fi println "\n===> multiple files and shell completion " -./datagen -s1 > tmp1 2> $INTOVOID -./datagen -s2 -g100K > tmp2 2> $INTOVOID -./datagen -s3 -g1M > tmp3 2> $INTOVOID +$DATAGEN -s1 > tmp1 2> $INTOVOID +$DATAGEN -s2 -g100K > tmp2 2> $INTOVOID +$DATAGEN -s3 -g1M > tmp3 2> $INTOVOID println "compress tmp* : " $ZSTD -f tmp* test -f tmp1.zst @@ -361,7 +363,7 @@ if [ -n "$DEVNULLRIGHTS" ] ; then # these tests requires sudo rights, which is uncommon. # they are only triggered if DEVNULLRIGHTS macro is defined. println "\n===> checking /dev/null permissions are unaltered " - ./datagen > tmp + $DATAGEN > tmp sudo $ZSTD tmp -o $INTOVOID # sudo rights could modify /dev/null permissions sudo $ZSTD tmp -c > $INTOVOID $ZSTD tmp -f -o tmp.zst @@ -442,11 +444,11 @@ test -f tmp3 test -f tmp4 println "test : survive a list of files which is text garbage (--filelist=FILE)" -./datagen > tmp_badList +$DATAGEN > tmp_badList $ZSTD -f --filelist=tmp_badList && die "should have failed : list is text garbage" println "test : survive a list of files which is binary garbage (--filelist=FILE)" -./datagen -P0 -g1M > tmp_badList +$DATAGEN -P0 -g1M > tmp_badList $ZSTD -qq -f --filelist=tmp_badList && die "should have failed : list is binary garbage" # let's avoid printing binary garbage on console println "test : try to overflow internal list of files (--filelist=FILE)" @@ -550,7 +552,7 @@ fi println "\n===> test sparse file support " -./datagen -g5M -P100 > tmpSparse +$DATAGEN -g5M -P100 > tmpSparse $ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen $DIFF -s tmpSparse tmpSparseRegen $ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse @@ -558,14 +560,14 @@ $DIFF -s tmpSparse tmpOutSparse $ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse $DIFF -s tmpSparse tmpOutNoSparse ls -ls tmpSparse* # look at file size and block size on disk -./datagen -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks) -./datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd +$DATAGEN -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks) +$DATAGEN -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd ls -ls tmpSparseOdd # look at file size and block size on disk println "\n Sparse Compatibility with Console :" println "Hello World 1 !" | $ZSTD | $ZSTD -d -c println "Hello World 2 !" | $ZSTD | $ZSTD -d | cat println "\n Sparse Compatibility with Append :" -./datagen -P100 -g1M > tmpSparse1M +$DATAGEN -P100 -g1M > tmpSparse1M cat tmpSparse1M tmpSparse1M > tmpSparse2M $ZSTD -v -f tmpSparse1M -o tmpSparseCompressed $ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated @@ -577,7 +579,7 @@ rm tmpSparse* println "\n===> stream-size mode" -./datagen -g11000 > tmp +$DATAGEN -g11000 > tmp println "test : basic file compression vs sized streaming compression" file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst) stream_size=$(cat tmp | $ZSTD -14 --stream-size=11000 | wc -c) @@ -610,9 +612,9 @@ rm -rf tmp* println "\n===> size-hint mode" -./datagen -g11000 > tmp -./datagen -g11000 > tmp2 -./datagen > tmpDict +$DATAGEN -g11000 > tmp +$DATAGEN -g11000 > tmp2 +$DATAGEN > tmpDict println "test : basic file compression vs hinted streaming compression" file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst) stream_size=$(cat tmp | $ZSTD -14 --size-hint=11000 | wc -c) @@ -641,9 +643,9 @@ cat tmp | $ZSTD -14 -f --size-hint=5500 | $ZSTD -t # considerably too low println "\n===> dictionary tests " println "- test with raw dict (content only) " -./datagen > tmpDict -./datagen -g1M | $MD5SUM > tmp1 -./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2 +$DATAGEN > tmpDict +$DATAGEN -g1M | $MD5SUM > tmp1 +$DATAGEN -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2 $DIFF -q tmp1 tmp2 println "- Create first dictionary " TESTFILE="$PRGDIR"/zstdcli.c @@ -662,7 +664,7 @@ $DIFF "$TESTFILE" result if [ -n "$hasMT" ] then println "- Test dictionary compression with multithreading " - ./datagen -g5M | $ZSTD -T2 -D tmpDict | $ZSTD -t -D tmpDict # fails with v1.3.2 + $DATAGEN -g5M | $ZSTD -T2 -D tmpDict | $ZSTD -t -D tmpDict # fails with v1.3.2 fi println "- Create second (different) dictionary " $ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC @@ -701,7 +703,7 @@ rm -rf dirTestDict println "- dictionary builder on bogus input" println "Hello World" > tmp $ZSTD --train-legacy -q tmp && die "Dictionary training should fail : not enough input source" -./datagen -P0 -g10M > tmp +$DATAGEN -P0 -g10M > tmp $ZSTD --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise" println "- Test -o before --train" rm -f tmpDict dictionary @@ -723,7 +725,7 @@ rm tmp* dictionary println "\n===> fastCover dictionary builder : advanced options " TESTFILE="$PRGDIR"/zstdcli.c -./datagen > tmpDict +$DATAGEN > tmpDict println "- Create first dictionary" $ZSTD --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp @@ -766,7 +768,7 @@ rm tmp* dictionary println "\n===> legacy dictionary builder " TESTFILE="$PRGDIR"/zstdcli.c -./datagen > tmpDict +$DATAGEN > tmpDict println "- Create first dictionary" $ZSTD --train-legacy=selectivity=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp @@ -794,7 +796,7 @@ rm tmp* dictionary println "\n===> integrity tests " println "test one file (tmp1.zst) " -./datagen > tmp1 +$DATAGEN > tmp1 $ZSTD tmp1 $ZSTD -t tmp1.zst $ZSTD --test tmp1.zst @@ -805,14 +807,14 @@ $ZSTD -t ./* && die "bad files not detected !" $ZSTD -t tmp1 && die "bad file not detected !" cp tmp1 tmp2.zst $ZSTD -t tmp2.zst && die "bad file not detected !" -./datagen -g0 > tmp3 +$DATAGEN -g0 > tmp3 $ZSTD -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad println "test --rm and --test combined " $ZSTD -t --rm tmp1.zst test -f tmp1.zst # check file is still present split -b16384 tmp1.zst tmpSplit. $ZSTD -t tmpSplit.* && die "bad file not detected !" -./datagen | $ZSTD -c | $ZSTD -t +$DATAGEN | $ZSTD -c | $ZSTD -t println "\n===> golden files tests " @@ -824,7 +826,7 @@ $ZSTD -c -r "$TESTDIR/golden-compression" | $ZSTD -t println "\n===> benchmark mode tests " println "bench one file" -./datagen > tmp1 +$DATAGEN > tmp1 $ZSTD -bi0 tmp1 println "bench multiple levels" $ZSTD -i0b0e3 tmp1 @@ -839,7 +841,7 @@ $ZSTD -b -d -i0 tmp1.zst println "\n===> zstd compatibility tests " -./datagen > tmp +$DATAGEN > tmp rm -f tmp.zst $ZSTD --format=zstd -f tmp test -f tmp.zst @@ -854,7 +856,7 @@ if [ $GZIPMODE -eq 1 ]; then GZIPEXE=1 gzip -V || GZIPEXE=0 if [ $GZIPEXE -eq 1 ]; then - ./datagen > tmp + $DATAGEN > tmp $ZSTD --format=gzip -f tmp gzip -t -v tmp.gz gzip -f tmp @@ -871,7 +873,7 @@ fi println "\n===> gzip frame tests " if [ $GZIPMODE -eq 1 ]; then - ./datagen > tmp + $DATAGEN > tmp $ZSTD -f --format=gzip tmp $ZSTD -f tmp cat tmp.gz tmp.zst tmp.gz tmp.zst | $ZSTD -d -f -o tmp @@ -882,7 +884,7 @@ else fi if [ $GZIPMODE -eq 1 ]; then - ./datagen > tmp + $DATAGEN > tmp rm -f tmp.zst $ZSTD --format=gzip --format=zstd -f tmp test -f tmp.zst @@ -898,7 +900,7 @@ if [ $LZMAMODE -eq 1 ]; then xz -Q -V && lzma -Q -V || XZEXE=0 if [ $XZEXE -eq 1 ]; then println "Testing zstd xz and lzma support" - ./datagen > tmp + $DATAGEN > tmp $ZSTD --format=lzma -f tmp $ZSTD --format=xz -f tmp xz -Q -t -v tmp.xz @@ -914,7 +916,7 @@ if [ $LZMAMODE -eq 1 ]; then ln -s $ZSTD ./lzma ln -s $ZSTD ./unlzma println "Testing xz and lzma symlinks" - ./datagen > tmp + $DATAGEN > tmp ./xz tmp xz -Q -d tmp.xz ./lzma tmp @@ -937,7 +939,7 @@ fi println "\n===> xz frame tests " if [ $LZMAMODE -eq 1 ]; then - ./datagen > tmp + $DATAGEN > tmp $ZSTD -f --format=xz tmp $ZSTD -f --format=lzma tmp $ZSTD -f tmp @@ -958,7 +960,7 @@ if [ $LZ4MODE -eq 1 ]; then LZ4EXE=1 lz4 -V || LZ4EXE=0 if [ $LZ4EXE -eq 1 ]; then - ./datagen > tmp + $DATAGEN > tmp $ZSTD --format=lz4 -f tmp lz4 -t -v tmp.lz4 lz4 -f tmp @@ -974,7 +976,7 @@ fi if [ $LZ4MODE -eq 1 ]; then println "\n===> lz4 frame tests " - ./datagen > tmp + $DATAGEN > tmp $ZSTD -f --format=lz4 tmp $ZSTD -f tmp cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | $ZSTD -d -f -o tmp @@ -1007,7 +1009,7 @@ println "\n===> tar extension tests " rm -f tmp tmp.tar tmp.tzst tmp.tgz tmp.txz tmp.tlz4 -./datagen > tmp +$DATAGEN > tmp tar cf tmp.tar tmp $ZSTD tmp.tar -o tmp.tzst rm tmp.tar @@ -1077,7 +1079,7 @@ then roundTripTest -g8M "3 --long=24 -T2" println "\n===> ovLog tests " - ./datagen -g2MB > tmp + $DATAGEN -g2MB > tmp refSize=$($ZSTD tmp -6 -c --zstd=wlog=18 | wc -c) ov9Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c) ov1Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=1 | wc -c) @@ -1101,9 +1103,9 @@ fi rm tmp* println "\n===> zstd --list/-l single frame tests " -./datagen > tmp1 -./datagen > tmp2 -./datagen > tmp3 +$DATAGEN > tmp1 +$DATAGEN > tmp2 +$DATAGEN > tmp3 $ZSTD tmp* $ZSTD -l ./*.zst $ZSTD -lv ./*.zst | grep "Decompressed Size:" # check that decompressed size is present in header @@ -1126,7 +1128,7 @@ println "test : detect truncated compressed file " TEST_DATA_FILE=truncatable-input.txt FULL_COMPRESSED_FILE=${TEST_DATA_FILE}.zst TRUNCATED_COMPRESSED_FILE=truncated-input.txt.zst -./datagen -g50000 > $TEST_DATA_FILE +$DATAGEN -g50000 > $TEST_DATA_FILE $ZSTD -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE dd bs=1 count=100 if=$FULL_COMPRESSED_FILE of=$TRUNCATED_COMPRESSED_FILE $ZSTD --list $TRUNCATED_COMPRESSED_FILE && die "-l must fail on truncated file" @@ -1145,7 +1147,7 @@ $ZSTD -l - tmp1.zst < tmp1.zst && die "-l does not work on stdin" $ZSTD -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty println "\n===> zstd --list/-l test with null files " -./datagen -g0 > tmp5 +$DATAGEN -g0 > tmp5 $ZSTD tmp5 $ZSTD -l tmp5.zst $ZSTD -l tmp5* && die "-l must fail on non-zstd file" @@ -1153,7 +1155,7 @@ $ZSTD -lv tmp5.zst | grep "Decompressed Size: 0.00 KB (0 B)" # check that 0 siz $ZSTD -lv tmp5* && die "-l must fail on non-zstd file" println "\n===> zstd --list/-l test with no content size field " -./datagen -g513K | $ZSTD > tmp6.zst +$DATAGEN -g513K | $ZSTD > tmp6.zst $ZSTD -l tmp6.zst $ZSTD -lv tmp6.zst | grep "Decompressed Size:" && die "Field :Decompressed Size: should not be available in this compressed file" @@ -1192,7 +1194,7 @@ then roundTripTest -g270000000 " --adapt" roundTripTest -g27000000 " --adapt=min=1,max=4" println "===> test: --adapt must fail on incoherent bounds " - ./datagen > tmp + $DATAGEN > tmp $ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds" println "\n===> rsyncable mode " @@ -1204,8 +1206,8 @@ fi println "\n===> patch-from tests" -./datagen -g1000 -P50 > tmp_dict -./datagen -g1000 -P10 > tmp_patch +$DATAGEN -g1000 -P50 > tmp_dict +$DATAGEN -g1000 -P10 > tmp_patch $ZSTD --memory=10000 --patch-from=tmp_dict tmp_patch -o tmp_patch_diff $ZSTD -d --memory=10000 --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon $DIFF -s tmp_patch_recon tmp_patch @@ -1273,7 +1275,7 @@ fi println "\n===> cover dictionary builder : advanced options " TESTFILE="$PRGDIR"/zstdcli.c -./datagen > tmpDict +$DATAGEN > tmpDict println "- Create first dictionary" $ZSTD --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp From f6d00c059fb2a55946ba0d5ef38b91e8f7e1b265 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 13 Jan 2020 14:22:46 -0800 Subject: [PATCH 161/402] [util] Fix readLineFromFile on Cygwin --- programs/util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/programs/util.c b/programs/util.c index 399507c2aab..4a3a3766005 100644 --- a/programs/util.c +++ b/programs/util.c @@ -278,7 +278,9 @@ U64 UTIL_getTotalFileSize(const char* const * fileNamesTable, unsigned nbFiles) static size_t readLineFromFile(char* buf, size_t len, FILE* file) { assert(!feof(file)); - CONTROL( fgets(buf, (int) len, file) == buf ); /* requires success */ + /* Work around Cygwin problem when len == 1 it returns NULL. */ + if (len <= 1) return 0; + CONTROL( fgets(buf, (int) len, file) ); { size_t linelen = strlen(buf); if (strlen(buf)==0) return 0; if (buf[linelen-1] == '\n') linelen--; From 3e8222be587f4d3471f65818d5494d4a6a8ab40c Mon Sep 17 00:00:00 2001 From: PhoebeHui Date: Fri, 17 Jan 2020 03:31:08 -0800 Subject: [PATCH 162/402] Add vcpkg installation instructions --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c94c7882a48..cd08f09a894 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,11 @@ example about how Meson is used to build this project. Note that default build type is **release**. +### VCPKG +If you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager, +you can build and install zstd with CMake integration in a single command: +- `vcpkg install zstd` + ### Visual Studio (Windows) Going into `build` directory, you will find additional possibilities: From a11a9271d6c5946a6f29e358e2a297ceef8f0a56 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 17 Jan 2020 12:05:53 -0800 Subject: [PATCH 163/402] Fix lowLimit underflow in overflow correction --- lib/compress/zstd_compress_internal.h | 18 +++++++++++++++--- tests/playTests.sh | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index c76189cc148..243f0e075ee 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -745,7 +745,10 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, */ U32 const cycleMask = (1U << cycleLog) - 1; U32 const current = (U32)((BYTE const*)src - window->base); - U32 const newCurrent = (current & cycleMask) + maxDist; + U32 const currentCycle0 = current & cycleMask; + /* Exclude zero so that newCurrent - maxDist >= 1. */ + U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0; + U32 const newCurrent = currentCycle1 + maxDist; U32 const correction = current - newCurrent; assert((maxDist & cycleMask) == 0); assert(current > newCurrent); @@ -754,8 +757,17 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, window->base += correction; window->dictBase += correction; - window->lowLimit -= correction; - window->dictLimit -= correction; + if (window->lowLimit <= correction) window->lowLimit = 1; + else window->lowLimit -= correction; + if (window->dictLimit <= correction) window->dictLimit = 1; + else window->dictLimit -= correction; + + /* Ensure we can still reference the full window. */ + assert(newCurrent >= maxDist); + assert(newCurrent - maxDist >= 1); + /* Ensure that lowLimit and dictLimit didn't underflow. */ + assert(window->lowLimit <= newCurrent); + assert(window->dictLimit <= newCurrent); DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction, window->lowLimit); diff --git a/tests/playTests.sh b/tests/playTests.sh index ffb455a8e15..52cbf7d3e56 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1239,8 +1239,8 @@ roundTripTest -g18000017 -P88 17 roundTripTest -g18000018 -P94 18 roundTripTest -g18000019 -P96 19 -roundTripTest -g5000000000 -P99 1 -roundTripTest -g1700000000 -P0 "1 --zstd=strategy=6" # ensure btlazy2 can survive an overflow rescale +roundTripTest -g5000000000 -P99 "1 --zstd=wlog=27" +roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=27" # ensure btlazy2 can survive an overflow rescale fileRoundTripTest -g4193M -P99 1 From fa48af545f9c346ea7c325260d0773ba2a7afe8a Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 17 Jan 2020 12:22:29 -0800 Subject: [PATCH 164/402] Add --single-thread to zstd --help --- programs/zstdcli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index a9755421974..f57bf3c0cc8 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -153,6 +153,7 @@ static void usage_advanced(const char* programName) # ifdef ZSTD_MULTITHREAD DISPLAYOUT( " -T# : spawns # compression threads (default: 1, 0==# cores) \n"); DISPLAYOUT( " -B# : select size of each job (default: 0==automatic) \n"); + DISPLAYOUT( " --single-thread : use a single thread for both I/O and compression (result slightly different than -T1)\n"); DISPLAYOUT( "--rsyncable : compress using a rsync-friendly method (-B sets block size) \n"); # endif DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression)\n"); From 009f388457101bcc73d08e10d2ec241acae4cc65 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 17 Jan 2020 14:20:44 -0800 Subject: [PATCH 165/402] Fix playTests.sh for 32-bit mode --- tests/playTests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index 52cbf7d3e56..6ae5bd8cd20 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1239,8 +1239,8 @@ roundTripTest -g18000017 -P88 17 roundTripTest -g18000018 -P94 18 roundTripTest -g18000019 -P96 19 -roundTripTest -g5000000000 -P99 "1 --zstd=wlog=27" -roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=27" # ensure btlazy2 can survive an overflow rescale +roundTripTest -g5000000000 -P99 "1 --zstd=wlog=25" +roundTripTest -g3700000000 -P0 "1 --zstd=strategy=6,wlog=25" # ensure btlazy2 can survive an overflow rescale fileRoundTripTest -g4193M -P99 1 From 77387090201fe2a70d45b04dc6be2b67a9f2e38e Mon Sep 17 00:00:00 2001 From: PhoebeHui Date: Sun, 19 Jan 2020 23:51:40 -0800 Subject: [PATCH 166/402] Update comments --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cd08f09a894..cb956690db1 100644 --- a/README.md +++ b/README.md @@ -144,9 +144,16 @@ example about how Meson is used to build this project. Note that default build type is **release**. ### VCPKG -If you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager, -you can build and install zstd with CMake integration in a single command: -- `vcpkg install zstd` +You can build and install zstd [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install zstd + +The zstd port in vcpkg is kept up to date by Microsoft team members and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. ### Visual Studio (Windows) From 768adc07743c4121216fdca0d8b4a0d7184ebd3c Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 21 Jan 2020 18:57:16 -0800 Subject: [PATCH 167/402] Fix timefn on android --- programs/timefn.c | 2 +- programs/timefn.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/timefn.c b/programs/timefn.c index 096e1910bf4..4025063eb79 100644 --- a/programs/timefn.c +++ b/programs/timefn.c @@ -84,7 +84,7 @@ PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ - && defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + && defined(TIME_UTC) && !defined(__ANDROID__) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ #include /* abort */ #include /* perror */ diff --git a/programs/timefn.h b/programs/timefn.h index b156a33b676..0f2b12ce893 100644 --- a/programs/timefn.h +++ b/programs/timefn.h @@ -52,7 +52,7 @@ extern "C" { #define UTIL_TIME_INITIALIZER 0 #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ - && defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + && defined(TIME_UTC) && !defined(__ANDROID__) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ typedef struct timespec UTIL_time_t; #define UTIL_TIME_INITIALIZER { 0, 0 } From 7ec87cfb28d389b946452bd74dac884ace542f13 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 22 Jan 2020 11:17:30 -0800 Subject: [PATCH 168/402] Update comment in timefn --- programs/timefn.c | 5 +++-- programs/timefn.h | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/programs/timefn.c b/programs/timefn.c index 4025063eb79..8d92b3a70c7 100644 --- a/programs/timefn.c +++ b/programs/timefn.c @@ -82,9 +82,10 @@ PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) } - +/* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance. + Android also lacks it but does define TIME_UTC. */ #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ - && defined(TIME_UTC) && !defined(__ANDROID__) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + && defined(TIME_UTC) && !defined(__ANDROID__) #include /* abort */ #include /* perror */ diff --git a/programs/timefn.h b/programs/timefn.h index 0f2b12ce893..7636f1f4d1b 100644 --- a/programs/timefn.h +++ b/programs/timefn.h @@ -51,8 +51,10 @@ extern "C" { typedef PTime UTIL_time_t; #define UTIL_TIME_INITIALIZER 0 +/* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance. + Android also lacks it but does define TIME_UTC. */ #elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ - && defined(TIME_UTC) && !defined(__ANDROID__) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + && defined(TIME_UTC) && !defined(__ANDROID__) typedef struct timespec UTIL_time_t; #define UTIL_TIME_INITIALIZER { 0, 0 } From 6e3cd5b0243c51aaa4ce46ee6cf82bc7c576d832 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 23 Jan 2020 12:27:39 -0800 Subject: [PATCH 169/402] Move ZSTD_checkContinuity() to zstd_decompress_block.c --- lib/decompress/zstd_decompress.c | 11 ----------- lib/decompress/zstd_decompress_block.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index d92440ae8a2..8ca7c5e4189 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -559,17 +559,6 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) * Frame decoding ***************************************************************/ - -void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) -{ - if (dst != dctx->previousDstEnd) { /* not contiguous */ - dctx->dictEnd = dctx->previousDstEnd; - dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); - dctx->prefixStart = dst; - dctx->previousDstEnd = dst; - } -} - /** ZSTD_insertBlock() : * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */ size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize) diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index ce43c525545..0b9e50f67b7 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -1285,6 +1285,17 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, } +void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) +{ + if (dst != dctx->previousDstEnd) { /* not contiguous */ + dctx->dictEnd = dctx->previousDstEnd; + dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); + dctx->prefixStart = dst; + dctx->previousDstEnd = dst; + } +} + + size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) From cb2abc3dbe010113d9e00ca3b612bf61983145a2 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 23 Jan 2020 16:18:52 -0800 Subject: [PATCH 170/402] Fix performance regression on aarch64 with clang --- lib/decompress/huf_decompress.c | 11 ++++++----- lib/decompress/zstd_decompress_block.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 732e1c93bfc..e599070ae44 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -817,7 +817,7 @@ HUF_decompress4X2_usingDTable_internal_body( /* 16-32 symbols per loop (4-8 symbols per stream) */ for ( ; (endSignal) & (op4 < olimit); ) { -#ifdef __clang__ +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) HUF_DECODE_SYMBOLX2_2(op1, &bitD1); HUF_DECODE_SYMBOLX2_1(op1, &bitD1); HUF_DECODE_SYMBOLX2_2(op1, &bitD1); @@ -855,10 +855,11 @@ HUF_decompress4X2_usingDTable_internal_body( HUF_DECODE_SYMBOLX2_0(op2, &bitD2); HUF_DECODE_SYMBOLX2_0(op3, &bitD3); HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; + endSignal = LIKELY( + (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished)); #endif } diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index ce43c525545..33c812d04f4 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -580,7 +580,7 @@ typedef struct { * Precondition: *ip <= *op * Postcondition: *op - *op >= 8 */ -static void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) { +HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) { assert(*ip <= *op); if (offset < 8) { /* close range match, overlap */ From fa6a772f38f4ac2bea1a428743f2bcdd41fa267a Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 23 Jan 2020 17:54:48 -0800 Subject: [PATCH 171/402] Initialize dctx->bType to silence valgrind false positive --- lib/decompress/zstd_decompress.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 8ca7c5e4189..f87e2618418 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1159,6 +1159,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ dctx->litEntropy = dctx->fseEntropy = 0; dctx->dictID = 0; + dctx->bType = bt_reserved; ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ dctx->LLTptr = dctx->entropy.LLTable; From f34eab162f11e2f9af96112358f9a5361ec4dcb6 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 24 Jan 2020 14:12:25 -0800 Subject: [PATCH 172/402] updated CHANGELOG --- CHANGELOG | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 75043cb0a72..5e78e38b9e2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ v1.4.5 -perf: Improved decompression speed, +10% on clang, +5% on gcc, by @terrelln -cli: new command : provide list of files to de/compress within a file with --filelist=FILE, by @AhmedAbdellah19 -api: low latency blocks, new experimental parameter by @ephiepark +fix : Compression ratio regression on huge files (> 3 GB) using high levels (--ultra) and multithreading, by @terrelln +perf: Improved decompression speed: x64 : +10% (clang) / +5% (gcc); ARM : from +15% to +50%, depending on chip, by @terrelln +cli: new command --filelist=FILE : provide list of files within a file, by @AhmedAbdellah19 +cli: new command --patch-from=FILE (experimental) : generate diff from 2 files, by @bimbashrestha +api: controlled block size for lower latency, new experimental parameter by @ephiepark build: mingw cross-compilation from unix, by @Ericson2314 misc: bitflip analyzer tool, by @felixhandte From 5bcd6448b6eff5b9889adf48aa8df39758b49fd2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 24 Jan 2020 20:16:28 -0800 Subject: [PATCH 173/402] refactor of harness, for clarity (#1974) following #1953 (false positive, due to heuristic confusion) --- doc/educational_decoder/harness.c | 91 +++++++++++++------------------ 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/doc/educational_decoder/harness.c b/doc/educational_decoder/harness.c index a704f6bdb29..706005e9975 100644 --- a/doc/educational_decoder/harness.c +++ b/doc/educational_decoder/harness.c @@ -21,108 +21,93 @@ typedef unsigned char u8; // Protect against allocating too much memory for output #define MAX_OUTPUT_SIZE ((size_t)1024 * 1024 * 1024) -static size_t read_file(const char *path, u8 **ptr) +// Error message then exit +#define ERR_OUT(...) { fprintf(stderr, __VA_ARGS__); exit(1); } + + +typedef struct { + u8* address; + size_t size; +} buffer_s; + +static void freeBuffer(buffer_s b) { free(b.address); } + +static buffer_s read_file(const char *path) { FILE* const f = fopen(path, "rb"); - if (!f) { - fprintf(stderr, "failed to open file %s \n", path); - exit(1); - } + if (!f) ERR_OUT("failed to open file %s \n", path); fseek(f, 0L, SEEK_END); size_t const size = (size_t)ftell(f); rewind(f); - *ptr = malloc(size); - if (!ptr) { - fprintf(stderr, "failed to allocate memory to hold %s \n", path); - exit(1); - } + void* const ptr = malloc(size); + if (!ptr) ERR_OUT("failed to allocate memory to hold %s \n", path); - size_t const read = fread(*ptr, 1, size, f); - if (read != size) { /* must read everything in one pass */ - fprintf(stderr, "error while reading file %s \n", path); - exit(1); - } + size_t const read = fread(ptr, 1, size, f); + if (read != size) ERR_OUT("error while reading file %s \n", path); fclose(f); - - return read; + buffer_s const b = { ptr, size }; + return b; } -static void write_file(const char *path, const u8 *ptr, size_t size) +static void write_file(const char* path, const u8* ptr, size_t size) { FILE* const f = fopen(path, "wb"); - if (!f) { - fprintf(stderr, "failed to open file %s \n", path); - exit(1); - } + if (!f) ERR_OUT("failed to open file %s \n", path); size_t written = 0; while (written < size) { written += fwrite(ptr+written, 1, size, f); - if (ferror(f)) { - fprintf(stderr, "error while writing file %s\n", path); - exit(1); - } } + if (ferror(f)) ERR_OUT("error while writing file %s\n", path); + } fclose(f); } int main(int argc, char **argv) { - if (argc < 3) { - fprintf(stderr, "usage: %s [dictionary] \n", - argv[0]); + if (argc < 3) + ERR_OUT("usage: %s [dictionary] \n", argv[0]); - return 1; - } + buffer_s const input = read_file(argv[1]); - u8* input; - size_t const input_size = read_file(argv[1], &input); - - u8* dict = NULL; - size_t dict_size = 0; + buffer_s dict = { NULL, 0 }; if (argc >= 4) { - dict_size = read_file(argv[3], &dict); + dict = read_file(argv[3]); } - size_t out_capacity = ZSTD_get_decompressed_size(input, input_size); + size_t out_capacity = ZSTD_get_decompressed_size(input.address, input.size); if (out_capacity == (size_t)-1) { - out_capacity = MAX_COMPRESSION_RATIO * input_size; + out_capacity = MAX_COMPRESSION_RATIO * input.size; fprintf(stderr, "WARNING: Compressed data does not contain " "decompressed size, going to assume the compression " "ratio is at most %d (decompressed size of at most " "%u) \n", MAX_COMPRESSION_RATIO, (unsigned)out_capacity); } - if (out_capacity > MAX_OUTPUT_SIZE) { - fprintf(stderr, - "Required output size too large for this implementation \n"); - return 1; - } + if (out_capacity > MAX_OUTPUT_SIZE) + ERR_OUT("Required output size too large for this implementation \n"); u8* const output = malloc(out_capacity); - if (!output) { - fprintf(stderr, "failed to allocate memory \n"); - return 1; - } + if (!output) ERR_OUT("failed to allocate memory \n"); dictionary_t* const parsed_dict = create_dictionary(); - if (dict) { - parse_dictionary(parsed_dict, dict, dict_size); + if (dict.size) { + parse_dictionary(parsed_dict, dict.address, dict.size); } size_t const decompressed_size = ZSTD_decompress_with_dict(output, out_capacity, - input, input_size, + input.address, input.size, parsed_dict); free_dictionary(parsed_dict); write_file(argv[2], output, decompressed_size); - free(input); + freeBuffer(input); + freeBuffer(dict); free(output); - free(dict); return 0; } From 9a71d07aa4528f1de23abea5ac4446a6d847402d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 27 Jan 2020 11:39:29 -0800 Subject: [PATCH 174/402] added ability to remove error messages and dictionary support (#1975) for the benefit of smaller binary. --- doc/educational_decoder/Makefile | 3 +- doc/educational_decoder/README.md | 7 + doc/educational_decoder/harness.c | 5 + doc/educational_decoder/zstd_decompress.c | 252 ++++++++++++---------- 4 files changed, 147 insertions(+), 120 deletions(-) diff --git a/doc/educational_decoder/Makefile b/doc/educational_decoder/Makefile index 704f867661a..b49a08fd1e9 100644 --- a/doc/educational_decoder/Makefile +++ b/doc/educational_decoder/Makefile @@ -36,7 +36,7 @@ harness: $(HARNESS_FILES) $(CC) $(FLAGS) $^ -o $@ clean: - @$(RM) harness + @$(RM) harness *.o @$(RM) -rf harness.dSYM # MacOS specific test: harness @@ -59,4 +59,3 @@ test: harness @./harness tmp.zst tmp dictionary @$(DIFF) -s tmp README.md @$(RM) tmp* dictionary - @$(MAKE) clean diff --git a/doc/educational_decoder/README.md b/doc/educational_decoder/README.md index e3b9bf58e5a..c89451ca078 100644 --- a/doc/educational_decoder/README.md +++ b/doc/educational_decoder/README.md @@ -13,6 +13,13 @@ It also contains implementations of Huffman and FSE table decoding. [Zstandard format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md [format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md +While the library's primary objective is code clarity, +it also happens to compile into a small object file. +The object file can be made even smaller by removing error messages, +using the macro directive `ZDEC_NO_MESSAGE` at compilation time. +This can be reduced even further by foregoing dictionary support, +by defining `ZDEC_NO_DICTIONARY`. + `harness.c` provides a simple test harness around the decoder: harness [dictionary] diff --git a/doc/educational_decoder/harness.c b/doc/educational_decoder/harness.c index 706005e9975..2bbb619d050 100644 --- a/doc/educational_decoder/harness.c +++ b/doc/educational_decoder/harness.c @@ -95,7 +95,12 @@ int main(int argc, char **argv) dictionary_t* const parsed_dict = create_dictionary(); if (dict.size) { +#if defined (ZDEC_NO_DICTIONARY) + printf("dict.size = %zu \n", dict.size); + ERR_OUT("no dictionary support \n"); +#else parse_dictionary(parsed_dict, dict.address, dict.size); +#endif } size_t const decompressed_size = ZSTD_decompress_with_dict(output, out_capacity, diff --git a/doc/educational_decoder/zstd_decompress.c b/doc/educational_decoder/zstd_decompress.c index 64e1b8738d0..eb92af73053 100644 --- a/doc/educational_decoder/zstd_decompress.c +++ b/doc/educational_decoder/zstd_decompress.c @@ -10,25 +10,42 @@ /// Zstandard educational decoder implementation /// See https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md -#include -#include -#include -#include +#include // uint8_t, etc. +#include // malloc, free, exit +#include // fprintf +#include // memset, memcpy #include "zstd_decompress.h" -/******* UTILITY MACROS AND TYPES *********************************************/ -// Max block size decompressed size is 128 KB and literal blocks can't be -// larger than their block -#define MAX_LITERALS_SIZE ((size_t)128 * 1024) +/******* IMPORTANT CONSTANTS *********************************************/ + +// Zstandard frame +// "Magic_Number +// 4 Bytes, little-endian format. Value : 0xFD2FB528" +#define ZSTD_MAGIC_NUMBER 0xFD2FB528U + +// The size of `Block_Content` is limited by `Block_Maximum_Size`, +#define ZSTD_BLOCK_SIZE_MAX ((size_t)128 * 1024) + +// literal blocks can't be larger than their block +#define MAX_LITERALS_SIZE ZSTD_BLOCK_SIZE_MAX + + +/******* UTILITY MACROS AND TYPES *********************************************/ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#if defined(ZDEC_NO_MESSAGE) +#define MESSAGE(...) +#else +#define MESSAGE(...) fprintf(stderr, "" __VA_ARGS__) +#endif + /// This decoder calls exit(1) when it encounters an error, however a production /// library should propagate error codes #define ERROR(s) \ do { \ - fprintf(stderr, "Error: %s\n", s); \ + MESSAGE("Error: %s\n", s); \ exit(1); \ } while (0) #define INP_SIZE() \ @@ -39,12 +56,12 @@ #define BAD_ALLOC() ERROR("Memory allocation error") #define IMPOSSIBLE() ERROR("An impossibility has occurred") -typedef uint8_t u8; +typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; -typedef int8_t i8; +typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; @@ -176,10 +193,6 @@ static void HUF_init_dtable_usingweights(HUF_dtable *const table, /// Free the malloc'ed parts of a decoding table static void HUF_free_dtable(HUF_dtable *const dtable); - -/// Deep copy a decoding table, so that it can be used and free'd without -/// impacting the source table. -static void HUF_copy_dtable(HUF_dtable *const dst, const HUF_dtable *const src); /*** END HUFFMAN PRIMITIVES ***********/ /*** FSE PRIMITIVES *******************/ @@ -241,10 +254,6 @@ static void FSE_init_dtable_rle(FSE_dtable *const dtable, const u8 symb); /// Free the malloc'ed parts of a decoding table static void FSE_free_dtable(FSE_dtable *const dtable); - -/// Deep copy a decoding table, so that it can be used and free'd without -/// impacting the source table. -static void FSE_copy_dtable(FSE_dtable *const dst, const FSE_dtable *const src); /*** END FSE PRIMITIVES ***************/ /******* END IMPLEMENTATION PRIMITIVE PROTOTYPES ******************************/ @@ -373,7 +382,7 @@ static void execute_match_copy(frame_context_t *const ctx, size_t offset, size_t ZSTD_decompress(void *const dst, const size_t dst_len, const void *const src, const size_t src_len) { - dictionary_t* uninit_dict = create_dictionary(); + dictionary_t* const uninit_dict = create_dictionary(); size_t const decomp_size = ZSTD_decompress_with_dict(dst, dst_len, src, src_len, uninit_dict); free_dictionary(uninit_dict); @@ -417,12 +426,7 @@ static void decompress_data(frame_context_t *const ctx, ostream_t *const out, static void decode_frame(ostream_t *const out, istream_t *const in, const dictionary_t *const dict) { const u32 magic_number = (u32)IO_read_bits(in, 32); - // Zstandard frame - // - // "Magic_Number - // - // 4 Bytes, little-endian format. Value : 0xFD2FB528" - if (magic_number == 0xFD2FB528U) { + if (magic_number == ZSTD_MAGIC_NUMBER) { // ZSTD frame decode_data_frame(out, in, dict); @@ -576,43 +580,6 @@ static void parse_frame_header(frame_header_t *const header, } } -/// A dictionary acts as initializing values for the frame context before -/// decompression, so we implement it by applying it's predetermined -/// tables and content to the context before beginning decompression -static void frame_context_apply_dict(frame_context_t *const ctx, - const dictionary_t *const dict) { - // If the content pointer is NULL then it must be an empty dict - if (!dict || !dict->content) - return; - - // If the requested dictionary_id is non-zero, the correct dictionary must - // be present - if (ctx->header.dictionary_id != 0 && - ctx->header.dictionary_id != dict->dictionary_id) { - ERROR("Wrong dictionary provided"); - } - - // Copy the dict content to the context for references during sequence - // execution - ctx->dict_content = dict->content; - ctx->dict_content_len = dict->content_size; - - // If it's a formatted dict copy the precomputed tables in so they can - // be used in the table repeat modes - if (dict->dictionary_id != 0) { - // Deep copy the entropy tables so they can be freed independently of - // the dictionary struct - HUF_copy_dtable(&ctx->literals_dtable, &dict->literals_dtable); - FSE_copy_dtable(&ctx->ll_dtable, &dict->ll_dtable); - FSE_copy_dtable(&ctx->of_dtable, &dict->of_dtable); - FSE_copy_dtable(&ctx->ml_dtable, &dict->ml_dtable); - - // Copy the repeated offsets - memcpy(ctx->previous_offsets, dict->previous_offsets, - sizeof(ctx->previous_offsets)); - } -} - /// Decompress the data from a frame block by block static void decompress_data(frame_context_t *const ctx, ostream_t *const out, istream_t *const in) { @@ -1411,7 +1378,7 @@ size_t ZSTD_get_decompressed_size(const void *src, const size_t src_len) { { const u32 magic_number = (u32)IO_read_bits(&in, 32); - if (magic_number == 0xFD2FB528U) { + if (magic_number == ZSTD_MAGIC_NUMBER) { // ZSTD frame frame_header_t header; parse_frame_header(&header, &in); @@ -1431,17 +1398,33 @@ size_t ZSTD_get_decompressed_size(const void *src, const size_t src_len) { /******* END OUTPUT SIZE COUNTING *********************************************/ /******* DICTIONARY PARSING ***************************************************/ -#define DICT_SIZE_ERROR() ERROR("Dictionary size cannot be less than 8 bytes") -#define NULL_SRC() ERROR("Tried to create dictionary with pointer to null src"); - dictionary_t* create_dictionary() { - dictionary_t* dict = calloc(1, sizeof(dictionary_t)); + dictionary_t* const dict = calloc(1, sizeof(dictionary_t)); if (!dict) { BAD_ALLOC(); } return dict; } +/// Free an allocated dictionary +void free_dictionary(dictionary_t *const dict) { + HUF_free_dtable(&dict->literals_dtable); + FSE_free_dtable(&dict->ll_dtable); + FSE_free_dtable(&dict->of_dtable); + FSE_free_dtable(&dict->ml_dtable); + + free(dict->content); + + memset(dict, 0, sizeof(dictionary_t)); + + free(dict); +} + + +#if !defined(ZDEC_NO_DICTIONARY) +#define DICT_SIZE_ERROR() ERROR("Dictionary size cannot be less than 8 bytes") +#define NULL_SRC() ERROR("Tried to create dictionary with pointer to null src"); + static void init_dictionary_content(dictionary_t *const dict, istream_t *const in); @@ -1513,19 +1496,93 @@ static void init_dictionary_content(dictionary_t *const dict, memcpy(dict->content, content, dict->content_size); } -/// Free an allocated dictionary -void free_dictionary(dictionary_t *const dict) { - HUF_free_dtable(&dict->literals_dtable); - FSE_free_dtable(&dict->ll_dtable); - FSE_free_dtable(&dict->of_dtable); - FSE_free_dtable(&dict->ml_dtable); +static void HUF_copy_dtable(HUF_dtable *const dst, + const HUF_dtable *const src) { + if (src->max_bits == 0) { + memset(dst, 0, sizeof(HUF_dtable)); + return; + } - free(dict->content); + const size_t size = (size_t)1 << src->max_bits; + dst->max_bits = src->max_bits; - memset(dict, 0, sizeof(dictionary_t)); + dst->symbols = malloc(size); + dst->num_bits = malloc(size); + if (!dst->symbols || !dst->num_bits) { + BAD_ALLOC(); + } - free(dict); + memcpy(dst->symbols, src->symbols, size); + memcpy(dst->num_bits, src->num_bits, size); } + +static void FSE_copy_dtable(FSE_dtable *const dst, const FSE_dtable *const src) { + if (src->accuracy_log == 0) { + memset(dst, 0, sizeof(FSE_dtable)); + return; + } + + size_t size = (size_t)1 << src->accuracy_log; + dst->accuracy_log = src->accuracy_log; + + dst->symbols = malloc(size); + dst->num_bits = malloc(size); + dst->new_state_base = malloc(size * sizeof(u16)); + if (!dst->symbols || !dst->num_bits || !dst->new_state_base) { + BAD_ALLOC(); + } + + memcpy(dst->symbols, src->symbols, size); + memcpy(dst->num_bits, src->num_bits, size); + memcpy(dst->new_state_base, src->new_state_base, size * sizeof(u16)); +} + +/// A dictionary acts as initializing values for the frame context before +/// decompression, so we implement it by applying it's predetermined +/// tables and content to the context before beginning decompression +static void frame_context_apply_dict(frame_context_t *const ctx, + const dictionary_t *const dict) { + // If the content pointer is NULL then it must be an empty dict + if (!dict || !dict->content) + return; + + // If the requested dictionary_id is non-zero, the correct dictionary must + // be present + if (ctx->header.dictionary_id != 0 && + ctx->header.dictionary_id != dict->dictionary_id) { + ERROR("Wrong dictionary provided"); + } + + // Copy the dict content to the context for references during sequence + // execution + ctx->dict_content = dict->content; + ctx->dict_content_len = dict->content_size; + + // If it's a formatted dict copy the precomputed tables in so they can + // be used in the table repeat modes + if (dict->dictionary_id != 0) { + // Deep copy the entropy tables so they can be freed independently of + // the dictionary struct + HUF_copy_dtable(&ctx->literals_dtable, &dict->literals_dtable); + FSE_copy_dtable(&ctx->ll_dtable, &dict->ll_dtable); + FSE_copy_dtable(&ctx->of_dtable, &dict->of_dtable); + FSE_copy_dtable(&ctx->ml_dtable, &dict->ml_dtable); + + // Copy the repeated offsets + memcpy(ctx->previous_offsets, dict->previous_offsets, + sizeof(ctx->previous_offsets)); + } +} + +#else // ZDEC_NO_DICTIONARY is defined + +static void frame_context_apply_dict(frame_context_t *const ctx, + const dictionary_t *const dict) { + (void)ctx; + if (dict && dict->content) ERROR("dictionary not supported"); +} + +#endif /******* END DICTIONARY PARSING ***********************************************/ /******* IO STREAM OPERATIONS *************************************************/ @@ -1945,26 +2002,6 @@ static void HUF_free_dtable(HUF_dtable *const dtable) { free(dtable->num_bits); memset(dtable, 0, sizeof(HUF_dtable)); } - -static void HUF_copy_dtable(HUF_dtable *const dst, - const HUF_dtable *const src) { - if (src->max_bits == 0) { - memset(dst, 0, sizeof(HUF_dtable)); - return; - } - - const size_t size = (size_t)1 << src->max_bits; - dst->max_bits = src->max_bits; - - dst->symbols = malloc(size); - dst->num_bits = malloc(size); - if (!dst->symbols || !dst->num_bits) { - BAD_ALLOC(); - } - - memcpy(dst->symbols, src->symbols, size); - memcpy(dst->num_bits, src->num_bits, size); -} /******* END HUFFMAN PRIMITIVES ***********************************************/ /******* FSE PRIMITIVES *******************************************************/ @@ -2279,25 +2316,4 @@ static void FSE_free_dtable(FSE_dtable *const dtable) { free(dtable->new_state_base); memset(dtable, 0, sizeof(FSE_dtable)); } - -static void FSE_copy_dtable(FSE_dtable *const dst, const FSE_dtable *const src) { - if (src->accuracy_log == 0) { - memset(dst, 0, sizeof(FSE_dtable)); - return; - } - - size_t size = (size_t)1 << src->accuracy_log; - dst->accuracy_log = src->accuracy_log; - - dst->symbols = malloc(size); - dst->num_bits = malloc(size); - dst->new_state_base = malloc(size * sizeof(u16)); - if (!dst->symbols || !dst->num_bits || !dst->new_state_base) { - BAD_ALLOC(); - } - - memcpy(dst->symbols, src->symbols, size); - memcpy(dst->num_bits, src->num_bits, size); - memcpy(dst->new_state_base, src->new_state_base, size * sizeof(u16)); -} /******* END FSE PRIMITIVES ***************************************************/ From 8fe562a7701ca3192359ca6faac74b1a5846a681 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 28 Jan 2020 11:29:43 -0800 Subject: [PATCH 175/402] [automated_benchmarking] Make arguments optional and add --dict argument (#1968) * Make arugments optional and add --dict argument * Removing accidental print statement * Change to more likely scenario for dictionary compression benchmark --- tests/Makefile | 2 +- tests/README.md | 33 ++++--- tests/automated_benchmarking.py | 157 ++++++++++++++++++++++++-------- 3 files changed, 140 insertions(+), 52 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 241e3f2b412..a27f1dd5bb7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -238,7 +238,7 @@ versionsTest: clean $(PYTHON) test-zstd-versions.py automated_benchmarking: clean - $(PYTHON) automated_benchmarking.py golden-compression 1 current 1 "" 60 + $(PYTHON) automated_benchmarking.py checkTag: checkTag.c $(ZSTDDIR)/zstd.h $(CC) $(FLAGS) $< -o $@$(EXT) diff --git a/tests/README.md b/tests/README.md index 05df82e540a..23e00767c39 100644 --- a/tests/README.md +++ b/tests/README.md @@ -33,21 +33,32 @@ pull requests from the zstd repo and compare facebook:dev to all of them once, c will continuously get pull requests from the zstd repo and run benchmarks against facebook:dev. ``` -Example usage: python automated_benchmarking.py golden-compression 1 current 1 "" 60 +Example usage: python automated_benchmarking.py ``` ``` -usage: automated_benchmarking.py [-h] directory levels mode emails +usage: automated_benchmarking.py [-h] [--directory DIRECTORY] + [--levels LEVELS] [--iterations ITERATIONS] + [--emails EMAILS] [--frequency FREQUENCY] + [--mode MODE] [--dict DICT] -positional arguments: - directory directory with files to benchmark - levels levels to test eg ('1,2,3') - mode 'fastmode', 'onetime', 'current' or 'continuous' - iterations number of benchmark iterations to run - emails email addresses of people who will be alerted upon regression. - Only for continuous mode - frequency specifies the number of seconds to wait before each successive - check for new PRs in continuous mode +optional arguments: + -h, --help show this help message and exit + --directory DIRECTORY + directory with files to benchmark + --levels LEVELS levels to test eg ('1,2,3') + --iterations ITERATIONS + number of benchmark iterations to run + --emails EMAILS email addresses of people who will be alerted upon + regression. Only for continuous mode + --frequency FREQUENCY + specifies the number of seconds to wait before each + successive check for new PRs in continuous mode + --mode MODE 'fastmode', 'onetime', 'current', or 'continuous' (see + README.md for details) + --dict DICT filename of dictionary to use (when set, this + dictioanry will be used to compress the files provided + inside --directory) ``` #### `test-zstd-speed.py` - script for testing zstd speed difference between commits diff --git a/tests/automated_benchmarking.py b/tests/automated_benchmarking.py index a385c21b098..aaa3010dff2 100644 --- a/tests/automated_benchmarking.py +++ b/tests/automated_benchmarking.py @@ -94,16 +94,19 @@ def clone_and_build(build): return "../zstd" +def parse_benchmark_output(output): + idx = [i for i, d in enumerate(output) if d == "MB/s"] + return [float(output[idx[0] - 1]), float(output[idx[1] - 1])] + + def benchmark_single(executable, level, filename): - tmp = ( + return parse_benchmark_output(( subprocess.run( [executable, "-qb{}".format(level), filename], stderr=subprocess.PIPE ) .stderr.decode("utf-8") .split(" ") - ) - idx = [i for i, d in enumerate(tmp) if d == "MB/s"] - return [float(tmp[idx[0] - 1]), float(tmp[idx[1] - 1])] + )) def benchmark_n(executable, level, filename, n): @@ -129,6 +132,45 @@ def benchmark(build, filenames, levels, iterations): ] +def benchmark_dictionary_single(executable, filenames_directory, dictionary_filename, level, iterations): + cspeeds, dspeeds = [], [] + for _ in range(iterations): + output = subprocess.run([executable, "-qb{}".format(level), "-D", dictionary_filename, "-r", filenames_directory], stderr=subprocess.PIPE).stderr.decode("utf-8").split(" ") + cspeed, dspeed = parse_benchmark_output(output) + cspeeds.append(cspeed) + dspeeds.append(dspeed) + max_cspeed, max_dspeed = max(cspeeds), max(dspeeds) + print( + "Bench (executable={} level={} filenames_directory={}, dictionary_filename={}, iterations={}):\n\t[cspeed: {} MB/s, dspeed: {} MB/s]".format( + os.path.basename(executable), + level, + os.path.basename(filenames_directory), + os.path.basename(dictionary_filename), + iterations, + max_cspeed, + max_dspeed, + ) + ) + return (max_cspeed, max_dspeed) + + +def benchmark_dictionary(build, filenames_directory, dictionary_filename, levels, iterations): + executable = clone_and_build(build) + return [benchmark_dictionary_single(executable, filenames_directory, dictionary_filename, l, iterations) for l in levels] + + +def parse_regressions_and_labels(old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build): + cspeed_reg = (old_cspeed - new_cspeed) / old_cspeed + dspeed_reg = (old_dspeed - new_dspeed) / old_dspeed + baseline_label = "{}:{} ({})".format( + baseline_build["user"], baseline_build["branch"], baseline_build["hash"] + ) + test_label = "{}:{} ({})".format( + test_build["user"], test_build["branch"], test_build["hash"] + ) + return cspeed_reg, dspeed_reg, baseline_label, test_label + + def get_regressions(baseline_build, test_build, iterations, filenames, levels): old = benchmark(baseline_build, filenames, levels, iterations) new = benchmark(test_build, filenames, levels, iterations) @@ -137,13 +179,8 @@ def get_regressions(baseline_build, test_build, iterations, filenames, levels): for k, filename in enumerate(filenames): old_cspeed, old_dspeed = old[j][k] new_cspeed, new_dspeed = new[j][k] - cspeed_reg = (old_cspeed - new_cspeed) / old_cspeed - dspeed_reg = (old_dspeed - new_dspeed) / old_dspeed - baseline_label = "{}:{} ({})".format( - baseline_build["user"], baseline_build["branch"], baseline_build["hash"] - ) - test_label = "{}:{} ({})".format( - test_build["user"], test_build["branch"], test_build["hash"] + cspeed_reg, dspeed_reg, baseline_build, test_label = parse_regressions_and_labels( + old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build ) if cspeed_reg > CSPEED_REGRESSION_TOLERANCE: regressions.append( @@ -171,14 +208,58 @@ def get_regressions(baseline_build, test_build, iterations, filenames, levels): ) return regressions -def main(filenames, levels, iterations, builds=None, emails=None, continuous=False, frequency=DEFAULT_MAX_API_CALL_FREQUENCY_SEC): +def get_regressions_dictionary(baseline_build, test_build, filenames_directory, dictionary_filename, levels, iterations): + old = benchmark_dictionary(baseline_build, filenames_directory, dictionary_filename, levels, iterations) + new = benchmark_dictionary(test_build, filenames_directory, dictionary_filename, levels, iterations) + regressions = [] + for j, level in enumerate(levels): + old_cspeed, old_dspeed = old[j] + new_cspeed, new_dspeed = new[j] + cspeed_reg, dspeed_reg, baesline_label, test_label = parse_regressions_and_labels( + old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build + ) + if cspeed_reg > CSPEED_REGRESSION_TOLERANCE: + regressions.append( + "[COMPRESSION REGRESSION] (level={} filenames_directory={} dictionary_filename={})\n\t{} -> {}\n\t{} -> {} ({:0.2f}%)".format( + level, + filenames_directory, + dictionary_filename, + baseline_label, + test_label, + old_cspeed, + new_cspeed, + cspeed_reg * 100.0, + ) + ) + if dspeed_reg > DSPEED_REGRESSION_TOLERANCE: + regressions.append( + "[DECOMPRESSION REGRESSION] (level={} filenames_directory={} dictionary_filename={})\n\t{} -> {}\n\t{} -> {} ({:0.2f}%)".format( + level, + filenames_directory, + dictionary_filename, + baseline_label, + test_label, + old_dspeed, + new_dspeed, + dspeed_reg * 100.0, + ) + ) + return regressions + + +def main(filenames, levels, iterations, builds=None, emails=None, continuous=False, frequency=DEFAULT_MAX_API_CALL_FREQUENCY_SEC, dictionary_filename=None): if builds == None: builds = get_new_open_pr_builds() while True: for test_build in builds: - regressions = get_regressions( - MASTER_BUILD, test_build, iterations, filenames, levels - ) + if dictionary_filename == None: + regressions = get_regressions( + MASTER_BUILD, test_build, iterations, filenames, levels + ) + else: + regressions = get_regressions_dictionary( + MASTER_BUILD, test_build, filenames, dictionary_filename, levels, iterations + ) body = "\n".join(regressions) if len(regressions) > 0: if emails != None: @@ -198,42 +279,38 @@ def main(filenames, levels, iterations, builds=None, emails=None, continuous=Fal if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument( - "directory", help="directory with files to benchmark", default="fuzz" - ) - parser.add_argument("levels", help="levels to test eg ('1,2,3')", default="1,2,3") - parser.add_argument( - "mode", help="'fastmode', 'onetime', 'current' or 'continuous'", default="onetime" - ) - parser.add_argument( - "iterations", help="number of benchmark iterations to run", default=5 - ) - parser.add_argument( - "emails", - help="email addresses of people who will be alerted upon regression. Only for continuous mode", - default=None, - ) - parser.add_argument( - "frequency", - help="specifies the number of seconds to wait before each successive check for new PRs in continuous mode", - default=DEFAULT_MAX_API_CALL_FREQUENCY_SEC - ) + + parser.add_argument("--directory", help="directory with files to benchmark", default="golden-compression") + parser.add_argument("--levels", help="levels to test eg ('1,2,3')", default="1") + parser.add_argument("--iterations", help="number of benchmark iterations to run", default="1") + parser.add_argument("--emails", help="email addresses of people who will be alerted upon regression. Only for continuous mode", default=None) + parser.add_argument("--frequency", help="specifies the number of seconds to wait before each successive check for new PRs in continuous mode", default=DEFAULT_MAX_API_CALL_FREQUENCY_SEC) + parser.add_argument("--mode", help="'fastmode', 'onetime', 'current', or 'continuous' (see README.md for details)", default="current") + parser.add_argument("--dict", help="filename of dictionary to use (when set, this dictioanry will be used to compress the files provided inside --directory)", default=None) args = parser.parse_args() - filenames = glob.glob("{}/**".format(args.directory)) + filenames = args.directory levels = [int(l) for l in args.levels.split(",")] mode = args.mode iterations = int(args.iterations) emails = args.emails frequency = int(args.frequency) + dictionary_filename = args.dict + + if dictionary_filename == None: + filenames = glob.glob("{}/**".format(filenames)) + + if (len(filenames) == 0): + print("0 files found") + quit() if mode == "onetime": - main(filenames, levels, iterations, frequency=frequency) + main(filenames, levels, iterations, frequency=frequenc, dictionary_filename=dictionary_filename) elif mode == "current": builds = [{"user": None, "branch": "None", "hash": None}] - main(filenames, levels, iterations, builds, frequency=frequency) + main(filenames, levels, iterations, builds, frequency=frequency, dictionary_filename=dictionary_filename) elif mode == "fastmode": builds = [{"user": "facebook", "branch": "master", "hash": None}] - main(filenames, levels, iterations, builds, frequency=frequency) + main(filenames, levels, iterations, builds, frequency=frequency, dictionary_filename=dictionary_filename) else: - main(filenames, levels, iterations, None, emails, True, frequency=frequency) + main(filenames, levels, iterations, None, emails, True, frequency=frequency, dictionary_filename=dictionary_filename) From e32e3e8662b73a5f5456b67311ea785ca9c55a2d Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 28 Jan 2020 20:37:04 -0800 Subject: [PATCH 176/402] Improve wildcopy performance across the board --- lib/common/zstd_internal.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 0bb67783f53..d0b014358e5 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -215,7 +215,7 @@ typedef enum { * - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart. * The src buffer must be before the dst buffer. */ -MEM_STATIC FORCE_INLINE_ATTR DONT_VECTORIZE +MEM_STATIC FORCE_INLINE_ATTR void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype) { ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src; @@ -232,14 +232,13 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e } while (op < oend); } else { assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN); - /* Separate out the first two COPY16() calls because the copy length is + /* Separate out the first COPY16() call because the copy length is * almost certain to be short, so the branches have different - * probabilities. - * On gcc-9 unrolling once is +1.6%, twice is +2%, thrice is +1.8%. - * On clang-8 unrolling once is +1.4%, twice is +3.3%, thrice is +3%. + * probabilities. Since it is almost certain to be short, only do + * one COPY16() in the first call. Then, do two calls per loop since + * at that point it is more likely to have a high trip count. */ COPY16(op, ip); - COPY16(op, ip); if (op >= oend) return; do { COPY16(op, ip); From 9b049836c980d7fcb5201aa2f88ddac7dbf798d2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 28 Jan 2020 21:39:20 -0800 Subject: [PATCH 177/402] Typo baseline_build -> baseline_label --- tests/automated_benchmarking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/automated_benchmarking.py b/tests/automated_benchmarking.py index aaa3010dff2..50140e9fd1d 100644 --- a/tests/automated_benchmarking.py +++ b/tests/automated_benchmarking.py @@ -179,7 +179,7 @@ def get_regressions(baseline_build, test_build, iterations, filenames, levels): for k, filename in enumerate(filenames): old_cspeed, old_dspeed = old[j][k] new_cspeed, new_dspeed = new[j][k] - cspeed_reg, dspeed_reg, baseline_build, test_label = parse_regressions_and_labels( + cspeed_reg, dspeed_reg, baseline_label, test_label = parse_regressions_and_labels( old_cspeed, new_cspeed, old_dspeed, new_dspeed, baseline_build, test_build ) if cspeed_reg > CSPEED_REGRESSION_TOLERANCE: From 2f10019b92128bbc6098ab77ea3865ff496221ad Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 14:12:03 -0800 Subject: [PATCH 178/402] Adding --show-default-cparams (show cparams before compressing --- lib/compress/zstd_compress.c | 108 ------------------------ lib/compress/zstd_compress_internal.h | 113 ++++++++++++++++++++++++++ programs/zstdcli.c | 33 ++++++++ tests/playTests.sh | 12 +++ 4 files changed, 158 insertions(+), 108 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e11092b41f5..562893d2365 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4071,117 +4071,9 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) /*-===== Pre-defined compression levels =====-*/ -#define ZSTD_MAX_CLEVEL 22 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } -static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { -{ /* "default" - for any srcSize > 256 KB */ - /* W, C, H, S, L, TL, strat */ - { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ - { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ - { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ - { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ - { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ - { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */ - { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ - { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */ - { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ - { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ - { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ - { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ - { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ - { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */ - { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ - { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ - { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ - { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ - { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ - { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ - { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ - { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ - { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ -}, -{ /* for srcSize <= 256 KB */ - /* W, C, H, S, L, T, strat */ - { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ - { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ - { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/ - { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/ - { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ - { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ - { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ - { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ - { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ - { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 128 KB */ - /* W, C, H, S, L, T, strat */ - { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ - { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ - { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ - { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ - { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ - { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ - { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ - { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ - { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ - { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 16 KB */ - /* W, C, H, S, L, T, strat */ - { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ - { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ - { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ - { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ - { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ - { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ - { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ - { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ - { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ - { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ - { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ - { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ - { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ - { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ - { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ - { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -}; - /*! ZSTD_getCParams_internal() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 243f0e075ee..ae984b4bdcc 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -551,6 +551,119 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match, return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd); } +/*-************************************* + * Compression parameters + ***************************************/ + +#define ZSTD_MAX_CLEVEL 22 + +static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { +{ /* "default" - for any srcSize > 256 KB */ + /* W, C, H, S, L, TL, strat */ + { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ + { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ + { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ + { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ + { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ + { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */ + { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ + { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */ + { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ + { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ + { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ + { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ + { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ + { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */ + { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ + { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ + { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ + { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ + { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ + { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ + { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ + { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ + { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ +}, +{ /* for srcSize <= 256 KB */ + /* W, C, H, S, L, T, strat */ + { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ + { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ + { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/ + { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/ + { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ + { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ + { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ + { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ + { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ + { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 128 KB */ + /* W, C, H, S, L, T, strat */ + { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ + { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ + { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ + { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ + { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ + { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ + { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ + { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ + { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ + { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ + { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 16 KB */ + /* W, C, H, S, L, T, strat */ + { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ + { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ + { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ + { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ + { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ + { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ + { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ + { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ + { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ + { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ + { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ + { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ + { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ + { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ + { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ + { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +}; + /*-************************************* * Hashes diff --git a/programs/zstdcli.c b/programs/zstdcli.c index f57bf3c0cc8..35191ad794e 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -41,6 +41,7 @@ # include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ #endif #include "zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ +#include "zstd_compress_internal.h" /* ZSTD_compressionParameters, ZSTD_strategyMap */ /*-************************************ @@ -580,6 +581,7 @@ int main(int const argCount, const char* argv[]) separateFiles = 0, setRealTimePrio = 0, singleThread = 0, + showDefaultCParams = 0, ultra=0; double compressibility = 0.5; unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */ @@ -693,6 +695,7 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--rm")) { FIO_setRemoveSrcFile(prefs, 1); continue; } if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; } + if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } @@ -1170,6 +1173,17 @@ int main(int const argCount, const char* argv[]) } } #endif + if (showDefaultCParams) { + if (operation == zom_decompress) { + DISPLAY("error : can't use --show-default-cparams in decomrpession mode \n"); + CLEAN_RETURN(1); + } + if (!UTIL_isRegularFile(filenames->fileNames[0])) { + DISPLAY("error : can't use --show-default-cparams with non-regular files \n"); + CLEAN_RETURN(1); + } + } + if (dictFileName != NULL && patchFromDictFileName != NULL) { DISPLAY("error : can't use -D and --patch-from=# at the same time \n"); CLEAN_RETURN(1); @@ -1213,6 +1227,25 @@ int main(int const argCount, const char* argv[]) if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; + if (showDefaultCParams) { + size_t fileNb; + static const char* ZSTD_strategyMap[9 + 1] = { "", "ZSTD_fast", + "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", + "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; + for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { + const size_t fileSize = UTIL_getFileSize(filenames->fileNames[fileNb]); + const size_t cParamsIdx = (fileSize < 16 KB) ? 3 : ( (fileSize < 128 KB) ? 2 : ( (fileSize < 256 KB) ? 1 : 0) ); + ZSTD_compressionParameters cParams = ZSTD_defaultCParameters[cParamsIdx][cLevel]; + DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); + DISPLAY(" - windowLog : %u\n", (unsigned)cParams.windowLog); + DISPLAY(" - chainLog : %u\n", (unsigned)cParams.chainLog); + DISPLAY(" - searchLog : %u\n", (unsigned)cParams.searchLog); + DISPLAY(" - minMatch : %u\n", (unsigned)cParams.minMatch); + DISPLAY(" - targetLength : %u\n", (unsigned)cParams.targetLength); + DISPLAY(" - strategy : %s\n", ZSTD_strategyMap[(int)cParams.strategy]); + } + } + if ((filenames->tableSize==1) && outFileName) operationResult = FIO_compressFilename(prefs, outFileName, filenames->fileNames[0], dictFileName, cLevel, compressionParams); else diff --git a/tests/playTests.sh b/tests/playTests.sh index 6ae5bd8cd20..09fe92fcf9a 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -457,6 +457,18 @@ ls tmp* > tmpList $ZSTD -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3 # can trigger an overflow of internal file list rm -rf tmp* +println "test : show-default-cparams regular" +$DATAGEN > tmp +$ZSTD --show-default-cparams -f tmp +rm -rf tmp* + +println "test : show-default-cparams recursive" +mkdir tmp_files +$DATAGEN -g15000 > tmp_files/tmp1 +$DATAGEN -g129000 > tmp_files/tmp2 +$DATAGEN -g257000 > tmp_files/tmp3 +$ZSTD --show-default-cparams -f -r tmp_files +rm -rf tmp* println "\n===> Advanced compression parameters " println "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!" From 71754a26f85c2885fbdb116668307285333651d6 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 14:14:27 -0800 Subject: [PATCH 179/402] Update comment --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 35191ad794e..00ec799618c 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -41,7 +41,7 @@ # include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ #endif #include "zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ -#include "zstd_compress_internal.h" /* ZSTD_compressionParameters, ZSTD_strategyMap */ +#include "zstd_compress_internal.h" /* ZSTD_compressionParameters */ /*-************************************ From b660ef87f85646891211ce162c0dd1b38eba366e Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 14:29:04 -0800 Subject: [PATCH 180/402] Convertion nit U32 -> size_t --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 00ec799618c..b2a47e78247 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1233,7 +1233,7 @@ int main(int const argCount, const char* argv[]) "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { - const size_t fileSize = UTIL_getFileSize(filenames->fileNames[fileNb]); + const size_t fileSize = (size_t)UTIL_getFileSize(filenames->fileNames[fileNb]); const size_t cParamsIdx = (fileSize < 16 KB) ? 3 : ( (fileSize < 128 KB) ? 2 : ( (fileSize < 256 KB) ? 1 : 0) ); ZSTD_compressionParameters cParams = ZSTD_defaultCParameters[cParamsIdx][cLevel]; DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); From b0ceab4dc061ea82c38b899ab5dfe6a8b577841b Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 16:52:07 -0800 Subject: [PATCH 181/402] Moving default cparams back, checking for unknown file size, using getCParams() --- lib/compress/zstd_compress.c | 108 ++++++++++++++++++++++++ lib/compress/zstd_compress_internal.h | 113 -------------------------- programs/zstdcli.c | 22 +++-- 3 files changed, 118 insertions(+), 125 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 562893d2365..e11092b41f5 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -4071,9 +4071,117 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) /*-===== Pre-defined compression levels =====-*/ +#define ZSTD_MAX_CLEVEL 22 int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } +static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { +{ /* "default" - for any srcSize > 256 KB */ + /* W, C, H, S, L, TL, strat */ + { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ + { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ + { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ + { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ + { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ + { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */ + { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ + { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */ + { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ + { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ + { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ + { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ + { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ + { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */ + { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ + { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ + { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ + { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ + { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ + { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ + { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ + { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ + { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ +}, +{ /* for srcSize <= 256 KB */ + /* W, C, H, S, L, T, strat */ + { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ + { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ + { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/ + { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/ + { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ + { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ + { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ + { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ + { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ + { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 128 KB */ + /* W, C, H, S, L, T, strat */ + { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ + { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ + { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ + { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ + { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ + { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ + { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ + { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ + { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ + { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ + { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 16 KB */ + /* W, C, H, S, L, T, strat */ + { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ + { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ + { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ + { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ + { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ + { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ + { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ + { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ + { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ + { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ + { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ + { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ + { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ + { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ + { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ + { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +}; + /*! ZSTD_getCParams_internal() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index ae984b4bdcc..243f0e075ee 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -551,119 +551,6 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match, return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd); } -/*-************************************* - * Compression parameters - ***************************************/ - -#define ZSTD_MAX_CLEVEL 22 - -static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { -{ /* "default" - for any srcSize > 256 KB */ - /* W, C, H, S, L, TL, strat */ - { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ - { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ - { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ - { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ - { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ - { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */ - { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ - { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */ - { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ - { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ - { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ - { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ - { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ - { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */ - { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ - { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ - { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ - { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ - { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ - { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ - { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ - { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ - { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ -}, -{ /* for srcSize <= 256 KB */ - /* W, C, H, S, L, T, strat */ - { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ - { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ - { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/ - { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/ - { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ - { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ - { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ - { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ - { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ - { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 128 KB */ - /* W, C, H, S, L, T, strat */ - { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ - { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ - { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ - { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ - { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ - { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ - { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ - { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ - { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ - { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 16 KB */ - /* W, C, H, S, L, T, strat */ - { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ - { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ - { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ - { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ - { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ - { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ - { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ - { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ - { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ - { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ - { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ - { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ - { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ - { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ - { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ - { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -}; - /*-************************************* * Hashes diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b2a47e78247..8936f2c5421 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -41,7 +41,6 @@ # include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ #endif #include "zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ -#include "zstd_compress_internal.h" /* ZSTD_compressionParameters */ /*-************************************ @@ -545,6 +544,11 @@ static int init_cLevel(void) { return ZSTDCLI_CLEVEL_DEFAULT; } +#define ZSTD_NB_STRATEGIES 9 +static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast", + "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", + "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; + typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom_list } zstd_operation_mode; #define CLEAN_RETURN(i) { operationResult = (i); goto _end; } @@ -1178,10 +1182,6 @@ int main(int const argCount, const char* argv[]) DISPLAY("error : can't use --show-default-cparams in decomrpession mode \n"); CLEAN_RETURN(1); } - if (!UTIL_isRegularFile(filenames->fileNames[0])) { - DISPLAY("error : can't use --show-default-cparams with non-regular files \n"); - CLEAN_RETURN(1); - } } if (dictFileName != NULL && patchFromDictFileName != NULL) { @@ -1229,14 +1229,12 @@ int main(int const argCount, const char* argv[]) if (showDefaultCParams) { size_t fileNb; - static const char* ZSTD_strategyMap[9 + 1] = { "", "ZSTD_fast", - "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", - "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { - const size_t fileSize = (size_t)UTIL_getFileSize(filenames->fileNames[fileNb]); - const size_t cParamsIdx = (fileSize < 16 KB) ? 3 : ( (fileSize < 128 KB) ? 2 : ( (fileSize < 256 KB) ? 1 : 0) ); - ZSTD_compressionParameters cParams = ZSTD_defaultCParameters[cParamsIdx][cLevel]; - DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); + const size_t fileSize = UTIL_isRegularFile(filenames->fileNames[fileNb]) ? (size_t)UTIL_getFileSize(filenames->fileNames[fileNb]) : 0; + const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; + const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, (unsigned long long)fileSize, dictSize); + if (fileSize) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); + else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); DISPLAY(" - windowLog : %u\n", (unsigned)cParams.windowLog); DISPLAY(" - chainLog : %u\n", (unsigned)cParams.chainLog); DISPLAY(" - searchLog : %u\n", (unsigned)cParams.searchLog); From 2a0771cfdbe5eccc9e097b2368906ec8d99a4674 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:05:33 -0800 Subject: [PATCH 182/402] Removing unnecessary cast --- programs/zstdcli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 8936f2c5421..3921efba171 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1230,9 +1230,9 @@ int main(int const argCount, const char* argv[]) if (showDefaultCParams) { size_t fileNb; for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { - const size_t fileSize = UTIL_isRegularFile(filenames->fileNames[fileNb]) ? (size_t)UTIL_getFileSize(filenames->fileNames[fileNb]) : 0; + unsigned long long fileSize = UTIL_isRegularFile(filenames->fileNames[fileNb]) ? UTIL_getFileSize(filenames->fileNames[fileNb]) : 0; const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; - const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, (unsigned long long)fileSize, dictSize); + const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize); if (fileSize) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); DISPLAY(" - windowLog : %u\n", (unsigned)cParams.windowLog); From c2033412928384c113411aa7430e6bb2956bdb34 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:07:22 -0800 Subject: [PATCH 183/402] Removing more casts --- programs/zstdcli.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 3921efba171..aa6df7b66c1 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1233,13 +1233,13 @@ int main(int const argCount, const char* argv[]) unsigned long long fileSize = UTIL_isRegularFile(filenames->fileNames[fileNb]) ? UTIL_getFileSize(filenames->fileNames[fileNb]) : 0; const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize); - if (fileSize) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); + if (fileSize) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], fileSize); else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); - DISPLAY(" - windowLog : %u\n", (unsigned)cParams.windowLog); - DISPLAY(" - chainLog : %u\n", (unsigned)cParams.chainLog); - DISPLAY(" - searchLog : %u\n", (unsigned)cParams.searchLog); - DISPLAY(" - minMatch : %u\n", (unsigned)cParams.minMatch); - DISPLAY(" - targetLength : %u\n", (unsigned)cParams.targetLength); + DISPLAY(" - windowLog : %u\n", cParams.windowLog); + DISPLAY(" - chainLog : %u\n", cParams.chainLog); + DISPLAY(" - searchLog : %u\n", cParams.searchLog); + DISPLAY(" - minMatch : %u\n", cParams.minMatch); + DISPLAY(" - targetLength : %u\n", cParams.targetLength); DISPLAY(" - strategy : %s\n", ZSTD_strategyMap[(int)cParams.strategy]); } } From 6bf05a53ab9db1aeb6a316161f479d68f148b90a Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:11:38 -0800 Subject: [PATCH 184/402] Documenting in the man file --- programs/zstd.1.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 8539deb9e77..5997ed6a59f 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -363,6 +363,11 @@ Compression of small files similar to the sample set will be greatly improved. `zstd --train-legacy=selectivity=8 FILEs` +* `--show-default-cparams`: + Shows the default compresssion parameters that will be used for a + particular src file. If the provided src file is not a regular file + (eg. named pipe), the cli will just output the default paramters. + BENCHMARK --------- From 6ad2f0d7d670afb644ba27a7f38f51bb9bb9d501 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:16:02 -0800 Subject: [PATCH 185/402] Adding back one cast and using UTIL_FILESIZE_UNKNOWN to check unknown file size --- programs/zstdcli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index aa6df7b66c1..40d1e621c28 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1230,10 +1230,10 @@ int main(int const argCount, const char* argv[]) if (showDefaultCParams) { size_t fileNb; for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { - unsigned long long fileSize = UTIL_isRegularFile(filenames->fileNames[fileNb]) ? UTIL_getFileSize(filenames->fileNames[fileNb]) : 0; + unsigned long long fileSize = UTIL_getFileSize(filenames->fileNames[fileNb]); const size_t dictSize = dictFileName != NULL ? (size_t)UTIL_getFileSize(dictFileName) : 0; const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize); - if (fileSize) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], fileSize); + if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); DISPLAY(" - windowLog : %u\n", cParams.windowLog); DISPLAY(" - chainLog : %u\n", cParams.chainLog); From 9d9cfa9ef9d92374c6f0fb59c16c3634fa0511f5 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:54:01 -0800 Subject: [PATCH 186/402] Adding assert and using ZSTD_STRATEGY_MAX as ZSTD_NB_STRATEGIES --- programs/zstdcli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 40d1e621c28..fed0a179f1f 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -544,7 +544,7 @@ static int init_cLevel(void) { return ZSTDCLI_CLEVEL_DEFAULT; } -#define ZSTD_NB_STRATEGIES 9 +#define ZSTD_NB_STRATEGIES ZSTD_STRATEGY_MAX static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast", "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; @@ -1240,6 +1240,7 @@ int main(int const argCount, const char* argv[]) DISPLAY(" - searchLog : %u\n", cParams.searchLog); DISPLAY(" - minMatch : %u\n", cParams.minMatch); DISPLAY(" - targetLength : %u\n", cParams.targetLength); + assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1); DISPLAY(" - strategy : %s\n", ZSTD_strategyMap[(int)cParams.strategy]); } } From f4ae6c0b942b9edf5322ff1c008d9f9495ce1f22 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 30 Jan 2020 17:54:42 -0800 Subject: [PATCH 187/402] Moving documentation and elaborating --- programs/zstd.1.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 5997ed6a59f..7dcc90339be 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -248,6 +248,14 @@ If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a `ZSTD_CLEVEL` just replaces the default compression level (`3`). It can be overridden by corresponding command line arguments. +### Misc. arguments + +* `--show-default-cparams`: + Shows the default compresssion parameters that will be used for a + particular src file. If the provided src file is not a regular file + (eg. named pipe), the cli will just output the default paramters. + That is, the parameters that are used when the src size is + unknown. DICTIONARY BUILDER ------------------ @@ -363,11 +371,6 @@ Compression of small files similar to the sample set will be greatly improved. `zstd --train-legacy=selectivity=8 FILEs` -* `--show-default-cparams`: - Shows the default compresssion parameters that will be used for a - particular src file. If the provided src file is not a regular file - (eg. named pipe), the cli will just output the default paramters. - BENCHMARK --------- From 0fa6c90e89a4ebbd944e3a75853bfcecd1215dd4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 31 Jan 2020 10:38:19 -0800 Subject: [PATCH 188/402] Moving to same category as -v --- programs/zstd.1.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 7dcc90339be..5b6505ba29d 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -228,6 +228,12 @@ the last one takes effect. `-vvV` also displays POSIX support. * `-v`: verbose mode +* `--show-default-cparams`: + Shows the default compresssion parameters that will be used for a + particular src file. If the provided src file is not a regular file + (eg. named pipe), the cli will just output the default paramters. + That is, the parameters that are used when the src size is + unknown. * `-q`, `--quiet`: suppress warnings, interactivity, and notifications. specify twice to suppress errors too. @@ -248,14 +254,6 @@ If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a `ZSTD_CLEVEL` just replaces the default compression level (`3`). It can be overridden by corresponding command line arguments. -### Misc. arguments - -* `--show-default-cparams`: - Shows the default compresssion parameters that will be used for a - particular src file. If the provided src file is not a regular file - (eg. named pipe), the cli will just output the default paramters. - That is, the parameters that are used when the src size is - unknown. DICTIONARY BUILDER ------------------ From 38d010eea048aed776fcea07e958883b18cea174 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 31 Jan 2020 10:47:17 -0800 Subject: [PATCH 189/402] Adding static assert and using it in cli --- programs/zstdcli.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index fed0a179f1f..01be5fdc16d 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -544,7 +544,10 @@ static int init_cLevel(void) { return ZSTDCLI_CLEVEL_DEFAULT; } +#define ZSTD_CLI_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1]) + #define ZSTD_NB_STRATEGIES ZSTD_STRATEGY_MAX + static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast", "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", "ZSTD_btopt", "ZSTD_btultra", "ZSTD_btultra2"}; @@ -1227,6 +1230,8 @@ int main(int const argCount, const char* argv[]) if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; + ZSTD_CLI_STATIC_ASSERT(ZSTD_NB_STRATEGIES >= ZSTD_STRATEGY_MIN && ZSTD_NB_STRATEGIES <= ZSTD_STRATEGY_MAX); + if (showDefaultCParams) { size_t fileNb; for (fileNb = 0; fileNb < (size_t)filenames->tableSize; fileNb++) { From 19473390d120792f1e2be239fa6e1d33d1e05a15 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 31 Jan 2020 10:54:02 -0800 Subject: [PATCH 190/402] Adding (void)ZSTD_strategyMap --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 01be5fdc16d..c91874751b2 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1255,7 +1255,7 @@ int main(int const argCount, const char* argv[]) else operationResult = FIO_compressMultipleFilenames(prefs, filenames->fileNames, (unsigned)filenames->tableSize, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams); #else - (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; /* not used when ZSTD_NOCOMPRESS set */ + (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; /* not used when ZSTD_NOCOMPRESS set */ DISPLAY("Compression not supported \n"); #endif } else { /* decompression or test */ From f33baa21c6f7509e3b1eec4157559233c9d0c7a8 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 31 Jan 2020 11:54:14 -0800 Subject: [PATCH 191/402] Removing assert and changing ratio cSize --- programs/benchzstd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 7439677c7f3..925a570b1a5 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -375,7 +375,6 @@ BMK_benchMemAdvancedNoAlloc( resPtr += thisBlockSize; remaining -= thisBlockSize; if (adv->mode == BMK_decodeOnly) { - assert(nbBlocks==0); cSizes[nbBlocks] = thisBlockSize; benchResult.cSize = thisBlockSize; } @@ -483,7 +482,7 @@ BMK_benchMemAdvancedNoAlloc( { int const ratioAccuracy = (ratio < 10.) ? 3 : 2; DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.*f),%6.*f MB/s ,%6.1f MB/s \r", marks[markNb], displayName, - (unsigned)srcSize, (unsigned)benchResult.cSize, + (unsigned)srcSize, (unsigned)cSize, ratioAccuracy, ratio, benchResult.cSpeed < (10 MB) ? 2 : 1, (double)benchResult.cSpeed / MB_UNIT, (double)benchResult.dSpeed / MB_UNIT); From ee8a712af360838afd8e0e3a08be35dd22a077bd Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 31 Jan 2020 15:49:07 -0800 Subject: [PATCH 192/402] Using appliedParams instead of supplied params --- lib/compress/zstd_compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index e11092b41f5..517c411de99 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3059,11 +3059,11 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, { size_t const dictID = cdict ? ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->workspace, params, cdict->dictContent, cdict->dictContentSize, + &cctx->workspace, &cctx->appliedParams, cdict->dictContent, cdict->dictContentSize, dictContentType, dtlm, cctx->entropyWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->workspace, params, dict, dictSize, + &cctx->workspace, &cctx->appliedParams, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); FORWARD_IF_ERROR(dictID); assert(dictID <= UINT_MAX); From 80c26117a99d200d802b607a912c5e3a79178747 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 3 Feb 2020 09:38:16 -0800 Subject: [PATCH 193/402] Line-wrapping --- lib/compress/zstd_compress.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 517c411de99..69ee7275939 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3059,8 +3059,9 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, { size_t const dictID = cdict ? ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->workspace, &cctx->appliedParams, cdict->dictContent, cdict->dictContentSize, - dictContentType, dtlm, cctx->entropyWorkspace) + &cctx->workspace, &cctx->appliedParams, cdict->dictContent, + cdict->dictContentSize, dictContentType, dtlm, + cctx->entropyWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, From d1389ac3ffadfc0fd105b62b4c462dba49217727 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 3 Feb 2020 09:52:39 -0800 Subject: [PATCH 194/402] Adding assert(NB_STRATEGIES == upperLimit) --- programs/zstdcli.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index c91874751b2..341f38cb254 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -544,9 +544,7 @@ static int init_cLevel(void) { return ZSTDCLI_CLEVEL_DEFAULT; } -#define ZSTD_CLI_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1]) - -#define ZSTD_NB_STRATEGIES ZSTD_STRATEGY_MAX +#define ZSTD_NB_STRATEGIES 9 static const char* ZSTD_strategyMap[ZSTD_NB_STRATEGIES + 1] = { "", "ZSTD_fast", "ZSTD_dfast", "ZSTD_greedy", "ZSTD_lazy", "ZSTD_lazy2", "ZSTD_btlazy2", @@ -1230,7 +1228,9 @@ int main(int const argCount, const char* argv[]) if (adaptMin > cLevel) cLevel = adaptMin; if (adaptMax < cLevel) cLevel = adaptMax; - ZSTD_CLI_STATIC_ASSERT(ZSTD_NB_STRATEGIES >= ZSTD_STRATEGY_MIN && ZSTD_NB_STRATEGIES <= ZSTD_STRATEGY_MAX); + /* Compare strategies constant with the ground truth */ + { ZSTD_bounds strategyBounds = ZSTD_cParam_getBounds(ZSTD_c_strategy); + assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound);} if (showDefaultCParams) { size_t fileNb; From 6a4258a08a0ce169a0bd5ce02ae35a5938ba1f5a Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 5 Feb 2020 16:55:00 -0800 Subject: [PATCH 195/402] Removing symbols already in unit tests and adding some new unit tests for missing symbols (#1985) * Removing symbols that are not being tested * Removing symbols used in zstdcli, fileio, dibio and benchzstd * Removing symbols used in zbuff and add test-zbuff to travis * Removing remaining symbols and adding unit tests instead * Removing symbols test entirely --- .circleci/config.yml | 2 +- .travis.yml | 5 ++ TESTING.md | 2 +- appveyor.yml | 2 +- build/meson/tests/meson.build | 9 -- tests/Makefile | 11 --- tests/fuzzer.c | 37 +++++++- tests/symbols.c | 164 ---------------------------------- tests/zbufftest.c | 6 ++ 9 files changed, 50 insertions(+), 188 deletions(-) delete mode 100644 tests/symbols.c diff --git a/.circleci/config.yml b/.circleci/config.yml index ca153d8356a..1565099b8ed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,7 +33,7 @@ jobs: make ppc64build; make clean make ppcbuild ; make clean make armbuild ; make clean - make -C tests test-legacy test-longmatch test-symbols; make clean + make -C tests test-legacy test-longmatch; make clean make -C lib libzstd-nomt; make clean # This step is only run on release tags. # It publishes the source tarball as artifacts and if the GITHUB_TOKEN diff --git a/.travis.yml b/.travis.yml index 8f7083c141a..282e0e7d642 100644 --- a/.travis.yml +++ b/.travis.yml @@ -168,6 +168,11 @@ matrix: script: - make test + - name: zbuff test + if: branch = master + script: + - make test-zbuff + - name: Versions Compatibility Test # 11.5mn if: branch = master script: diff --git a/TESTING.md b/TESTING.md index 551981b1405..42cd48e7019 100644 --- a/TESTING.md +++ b/TESTING.md @@ -11,7 +11,7 @@ They consist of the following tests: - Compilation on all supported targets (x86, x86_64, ARM, AArch64, PowerPC, and PowerPC64) - Compilation on various versions of gcc, clang, and g++ - `tests/playTests.sh` on x86_64, without the tests on long data (CLI tests) -- Small tests (`tests/legacy.c`, `tests/longmatch.c`, `tests/symbols.c`) on x64_64 +- Small tests (`tests/legacy.c`, `tests/longmatch.c`) on x64_64 Medium Tests ------------ diff --git a/appveyor.yml b/appveyor.yml index b483a0b5d09..94e56330b4b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,7 +14,7 @@ - COMPILER: "gcc" HOST: "mingw" PLATFORM: "x64" - SCRIPT: "make allzstd MOREFLAGS=-static && make -C tests test-symbols fullbench-lib" + SCRIPT: "make allzstd MOREFLAGS=-static && make -C tests fullbench-lib" ARTIFACT: "true" BUILD: "true" - COMPILER: "gcc" diff --git a/build/meson/tests/meson.build b/build/meson/tests/meson.build index 64eba6028d6..6b1282def5f 100644 --- a/build/meson/tests/meson.build +++ b/build/meson/tests/meson.build @@ -131,14 +131,6 @@ decodecorpus = executable('decodecorpus', dependencies: [ libzstd_dep, libm_dep ], install: false) -symbols_sources = [join_paths(zstd_rootdir, 'tests/symbols.c')] -symbols = executable('symbols', - symbols_sources, - include_directories: test_includes, - c_args: host_machine_os == os_windows ? '-DZSTD_DLL_IMPORT=1' : [], - dependencies: [ libzstd_dep ], - install: false) - poolTests_sources = [join_paths(zstd_rootdir, 'programs/util.c'), join_paths(zstd_rootdir, 'programs/timefn.c'), join_paths(zstd_rootdir, 'tests/poolTests.c'), @@ -219,7 +211,6 @@ test('test-zstream-3', timeout: 120) test('test-longmatch', longmatch, timeout: 36) test('test-invalidDictionaries', invalidDictionaries) # should be fast -test('test-symbols', symbols) # should be fast if 0 < legacy_level and legacy_level <= 4 test('test-legacy', legacy) # should be fast endif diff --git a/tests/Makefile b/tests/Makefile index a27f1dd5bb7..bcc84ddf1de 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -222,14 +222,6 @@ legacy : $(ZSTD_FILES) $(wildcard $(ZSTDDIR)/legacy/*.c) legacy.c decodecorpus : $(filter-out zstdc_zstd_compress.o, $(ZSTD_OBJECTS)) $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c decodecorpus.c $(CC) $(FLAGS) $^ -o $@$(EXT) -lm -symbols : symbols.c zstd-dll -ifneq (,$(filter Windows%,$(OS))) - cp $(ZSTDDIR)/dll/libzstd.dll . - $(CC) $(FLAGS) $< -o $@$(EXT) -DZSTD_DLL_IMPORT=1 libzstd.dll -else - $(CC) $(FLAGS) $< -o $@$(EXT) -Wl,-rpath=$(ZSTDDIR) $(ZSTDDIR)/libzstd.so # broken on Mac -endif - poolTests : $(PRGDIR)/util.c $(PRGDIR)/timefn.c poolTests.c $(ZSTDDIR)/common/pool.c $(ZSTDDIR)/common/threading.c $(ZSTDDIR)/common/zstd_common.c $(ZSTDDIR)/common/error_private.c $(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT) @@ -404,9 +396,6 @@ test-bigdict: bigdict test-invalidDictionaries: invalidDictionaries $(QEMU_SYS) ./invalidDictionaries -test-symbols: symbols - $(QEMU_SYS) ./symbols - test-legacy: legacy $(QEMU_SYS) ./legacy diff --git a/tests/fuzzer.c b/tests/fuzzer.c index bad23d47909..3c4aac7a8fc 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -366,6 +366,11 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "%i (OK) \n", mcl); } + DISPLAYLEVEL(3, "test%3u : ZSTD_versionNumber : ", testNb++); + { unsigned const vn = ZSTD_versionNumber(); + DISPLAYLEVEL(3, "%u (OK) \n", vn); + } + DISPLAYLEVEL(3, "test%3u : compress %u bytes : ", testNb++, (unsigned)CNBuffSize); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); if (cctx==NULL) goto _output_error; @@ -389,13 +394,18 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize test : ", testNb++); { unsigned long long const rSize = ZSTD_getFrameContentSize(compressedBuffer, cSize); if (rSize != CNBuffSize) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_getDecompressedSize test : ", testNb++); + { unsigned long long const rSize = ZSTD_getDecompressedSize(compressedBuffer, cSize); + if (rSize != CNBuffSize) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_findDecompressedSize test : ", testNb++); { unsigned long long const rSize = ZSTD_findDecompressedSize(compressedBuffer, cSize); if (rSize != CNBuffSize) goto _output_error; @@ -428,6 +438,31 @@ static int basicUnitTests(U32 const seed, double compressibility) } } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_checkCParams : ", testNb++); + { + ZSTD_parameters params = ZSTD_getParams(3, 0, 0); + assert(!ZSTD_checkCParams(params.cParams)); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_createDCtx_advanced and ZSTD_sizeof_DCtx: ", testNb++); + { + ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(ZSTD_defaultCMem); + assert(dctx != NULL); + assert(ZSTD_sizeof_DCtx(dctx) != 0); + ZSTD_freeDCtx(dctx); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : misc unaccounted for zstd symbols : ", testNb++); + { + DISPLAYLEVEL(3, "%p ", ZSTD_getDictID_fromDDict); + DISPLAYLEVEL(3, "%p ", ZSTD_createDStream_advanced); + DISPLAYLEVEL(3, "%p ", ZSTD_copyDCtx); + DISPLAYLEVEL(3, "%p ", ZSTD_nextInputType); + } + DISPLAYLEVEL(3, ": OK \n"); + DISPLAYLEVEL(3, "test%3i : decompress with null dict : ", testNb++); { ZSTD_DCtx* const dctx = ZSTD_createDCtx(); assert(dctx != NULL); { size_t const r = ZSTD_decompress_usingDict(dctx, diff --git a/tests/symbols.c b/tests/symbols.c deleted file mode 100644 index 4d9c6fc0c9e..00000000000 --- a/tests/symbols.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - - -#include -#include "zstd_errors.h" -#define ZSTD_STATIC_LINKING_ONLY -#include "zstd.h" -#define ZBUFF_DISABLE_DEPRECATE_WARNINGS -#define ZBUFF_STATIC_LINKING_ONLY -#include "zbuff.h" -#define ZDICT_DISABLE_DEPRECATE_WARNINGS -#define ZDICT_STATIC_LINKING_ONLY -#include "zdict.h" - -static const void *symbols[] = { -/* zstd.h */ - &ZSTD_versionNumber, - &ZSTD_compress, - &ZSTD_decompress, - &ZSTD_getDecompressedSize, - &ZSTD_findDecompressedSize, - &ZSTD_findFrameCompressedSize, - &ZSTD_getFrameContentSize, - &ZSTD_maxCLevel, - &ZSTD_compressBound, - &ZSTD_decompressBound, - &ZSTD_isError, - &ZSTD_getErrorName, - &ZSTD_createCCtx, - &ZSTD_freeCCtx, - &ZSTD_compressCCtx, - &ZSTD_createDCtx, - &ZSTD_freeDCtx, - &ZSTD_decompressDCtx, - &ZSTD_compress_usingDict, - &ZSTD_decompress_usingDict, - &ZSTD_createCDict, - &ZSTD_freeCDict, - &ZSTD_compress_usingCDict, - &ZSTD_createDDict, - &ZSTD_freeDDict, - &ZSTD_decompress_usingDDict, - &ZSTD_createCStream, - &ZSTD_freeCStream, - &ZSTD_initCStream, - &ZSTD_compressStream, - &ZSTD_flushStream, - &ZSTD_endStream, - &ZSTD_CStreamInSize, - &ZSTD_CStreamOutSize, - &ZSTD_createDStream, - &ZSTD_freeDStream, - &ZSTD_initDStream, - &ZSTD_decompressStream, - &ZSTD_DStreamInSize, - &ZSTD_DStreamOutSize, -/* zstd.h: advanced functions */ - &ZSTD_estimateCCtxSize, - &ZSTD_createCCtx_advanced, - &ZSTD_sizeof_CCtx, - &ZSTD_createCDict_advanced, - &ZSTD_sizeof_CDict, - &ZSTD_getCParams, - &ZSTD_getParams, - &ZSTD_checkCParams, - &ZSTD_adjustCParams, - &ZSTD_compress_advanced, - &ZSTD_isFrame, - &ZSTD_estimateDCtxSize, - &ZSTD_createDCtx_advanced, - &ZSTD_sizeof_DCtx, - &ZSTD_sizeof_DDict, - &ZSTD_getDictID_fromDict, - &ZSTD_getDictID_fromDDict, - &ZSTD_getDictID_fromFrame, - &ZSTD_createCStream_advanced, - &ZSTD_initCStream_srcSize, - &ZSTD_initCStream_usingDict, - &ZSTD_initCStream_advanced, - &ZSTD_initCStream_usingCDict, - &ZSTD_resetCStream, - &ZSTD_sizeof_CStream, - &ZSTD_createDStream_advanced, - &ZSTD_initDStream_usingDict, - &ZSTD_initDStream_usingDDict, - &ZSTD_resetDStream, - &ZSTD_sizeof_DStream, - &ZSTD_compressBegin, - &ZSTD_compressBegin_usingDict, - &ZSTD_compressBegin_advanced, - &ZSTD_copyCCtx, - &ZSTD_compressContinue, - &ZSTD_compressEnd, - &ZSTD_getFrameHeader, - &ZSTD_decompressBegin, - &ZSTD_decompressBegin_usingDict, - &ZSTD_copyDCtx, - &ZSTD_nextSrcSizeToDecompress, - &ZSTD_decompressContinue, - &ZSTD_nextInputType, - &ZSTD_getBlockSize, - &ZSTD_compressBlock, - &ZSTD_decompressBlock, - &ZSTD_insertBlock, -/* zstd_errors.h */ - &ZSTD_getErrorCode, - &ZSTD_getErrorString, -/* zbuff.h */ - &ZBUFF_createCCtx, - &ZBUFF_freeCCtx, - &ZBUFF_compressInit, - &ZBUFF_compressInitDictionary, - &ZBUFF_compressContinue, - &ZBUFF_compressFlush, - &ZBUFF_compressEnd, - &ZBUFF_createDCtx, - &ZBUFF_freeDCtx, - &ZBUFF_decompressInit, - &ZBUFF_decompressInitDictionary, - &ZBUFF_decompressContinue, - &ZBUFF_isError, - &ZBUFF_getErrorName, - &ZBUFF_recommendedCInSize, - &ZBUFF_recommendedCOutSize, - &ZBUFF_recommendedDInSize, - &ZBUFF_recommendedDOutSize, -/* zbuff.h: advanced functions */ - &ZBUFF_createCCtx_advanced, - &ZBUFF_createDCtx_advanced, - &ZBUFF_compressInit_advanced, -/* zdict.h */ - &ZDICT_trainFromBuffer, - &ZDICT_getDictID, - &ZDICT_isError, - &ZDICT_getErrorName, -/* zdict.h: advanced functions */ - &ZDICT_trainFromBuffer_cover, - &ZDICT_optimizeTrainFromBuffer_cover, - &ZDICT_trainFromBuffer_fastCover, - &ZDICT_optimizeTrainFromBuffer_fastCover, - &ZDICT_finalizeDictionary, - &ZDICT_trainFromBuffer_legacy, - &ZDICT_addEntropyTablesFromBuffer, - NULL, -}; - -int main(int argc, const char** argv) { - const void **symbol; - (void)argc; - (void)argv; - - for (symbol = symbols; *symbol != NULL; ++symbol) { - printf("%p\n", *symbol); - } - return 0; -} diff --git a/tests/zbufftest.c b/tests/zbufftest.c index 8a4a27907b0..f01d89e51c4 100644 --- a/tests/zbufftest.c +++ b/tests/zbufftest.c @@ -35,6 +35,7 @@ #define XXH_STATIC_LINKING_ONLY #include "xxhash.h" /* XXH64_* */ #include "util.h" +#include "assert.h" /*-************************************ @@ -180,6 +181,11 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo if (readSize+readSkipSize != cSize) goto _output_error; /* should have read the entire frame */ DISPLAYLEVEL(4, "OK \n"); + DISPLAYLEVEL(4, "test%3i : ZBUFF_recommendedCInSize : ", testNb++); { assert(ZBUFF_recommendedCInSize() != 0); } DISPLAYLEVEL(4, "OK \n"); + DISPLAYLEVEL(4, "test%3i : ZBUFF_recommendedCOutSize : ", testNb++); { assert(ZBUFF_recommendedCOutSize() != 0); } DISPLAYLEVEL(4, "OK \n"); + DISPLAYLEVEL(4, "test%3i : ZBUFF_recommendedDInSize : ", testNb++); { assert(ZBUFF_recommendedDInSize() != 0); } DISPLAYLEVEL(4, "OK \n"); + DISPLAYLEVEL(4, "test%3i : ZBUFF_recommendedDOutSize : ", testNb++); { assert(ZBUFF_recommendedDOutSize() != 0); } DISPLAYLEVEL(4, "OK \n"); + /* check regenerated data is byte exact */ DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++); { size_t i; From f627e1a1ae76b956aa060c1463aa8020dda0e168 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 6 Feb 2020 13:51:43 -0800 Subject: [PATCH 196/402] Displaying level in --show-default-cparams (#1991) * Displaying level in --show-default-cparams * Displaying actual enum value instead of level --- programs/zstdcli.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 341f38cb254..3ebecadcab2 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1240,13 +1240,13 @@ int main(int const argCount, const char* argv[]) const ZSTD_compressionParameters cParams = ZSTD_getCParams(cLevel, fileSize, dictSize); if (fileSize != UTIL_FILESIZE_UNKNOWN) DISPLAY("%s (%u bytes)\n", filenames->fileNames[fileNb], (unsigned)fileSize); else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); - DISPLAY(" - windowLog : %u\n", cParams.windowLog); - DISPLAY(" - chainLog : %u\n", cParams.chainLog); - DISPLAY(" - searchLog : %u\n", cParams.searchLog); - DISPLAY(" - minMatch : %u\n", cParams.minMatch); - DISPLAY(" - targetLength : %u\n", cParams.targetLength); + DISPLAY(" - windowLog : %u\n", cParams.windowLog); + DISPLAY(" - chainLog : %u\n", cParams.chainLog); + DISPLAY(" - searchLog : %u\n", cParams.searchLog); + DISPLAY(" - minMatch : %u\n", cParams.minMatch); + DISPLAY(" - targetLength : %u\n", cParams.targetLength); assert(cParams.strategy < ZSTD_NB_STRATEGIES + 1); - DISPLAY(" - strategy : %s\n", ZSTD_strategyMap[(int)cParams.strategy]); + DISPLAY(" - strategy : %s (%u)\n", ZSTD_strategyMap[(int)cParams.strategy], (unsigned)cParams.strategy); } } From 06a57cf57e3c4e887cadcf688e3081154f3f6db4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 6 Feb 2020 14:10:51 -0800 Subject: [PATCH 197/402] [build-issue] More portable header prefix usage (#) (#1987) * make 4.3 build issue fix * Changing header name and adding comment --- programs/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index b75314a83f4..a9ee3cb5311 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -94,9 +94,12 @@ endif VOID = /dev/null +# Make 4.3 doesn't support '\#' anymore (https://lwn.net/Articles/810071/) +NUM_SYMBOL := \# + # thread detection NO_THREAD_MSG := ==> no threads, building without multithreading support -HAVE_PTHREAD := $(shell printf '\#include \nint main(void) { return 0; }' > have_pthread.c && $(CC) $(FLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c) +HAVE_PTHREAD := $(shell printf '$(NUM_SYMBOL)include \nint main(void) { return 0; }' > have_pthread.c && $(CC) $(FLAGS) -o have_pthread$(EXT) have_pthread.c -pthread 2> $(VOID) && rm have_pthread$(EXT) && echo 1 || echo 0; rm have_pthread.c) HAVE_THREAD := $(shell [ "$(HAVE_PTHREAD)" -eq "1" -o -n "$(filter Windows%,$(OS))" ] && echo 1 || echo 0) ifeq ($(HAVE_THREAD), 1) THREAD_MSG := ==> building with threading support @@ -108,7 +111,7 @@ endif # zlib detection NO_ZLIB_MSG := ==> no zlib, building zstd without .gz support -HAVE_ZLIB := $(shell printf '\#include \nint main(void) { return 0; }' > have_zlib.c && $(CC) $(FLAGS) -o have_zlib$(EXT) have_zlib.c -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0; rm have_zlib.c) +HAVE_ZLIB := $(shell printf '$(NUM_SYMBOL)include \nint main(void) { return 0; }' > have_zlib.c && $(CC) $(FLAGS) -o have_zlib$(EXT) have_zlib.c -lz 2> $(VOID) && rm have_zlib$(EXT) && echo 1 || echo 0; rm have_zlib.c) ifeq ($(HAVE_ZLIB), 1) ZLIB_MSG := ==> building zstd with .gz compression support ZLIBCPP = -DZSTD_GZCOMPRESS -DZSTD_GZDECOMPRESS @@ -119,7 +122,7 @@ endif # lzma detection NO_LZMA_MSG := ==> no liblzma, building zstd without .xz/.lzma support -HAVE_LZMA := $(shell printf '\#include \nint main(void) { return 0; }' > have_lzma.c && $(CC) $(FLAGS) -o have_lzma$(EXT) have_lzma.c -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0; rm have_lzma.c) +HAVE_LZMA := $(shell printf '$(NUM_SYMBOL)include \nint main(void) { return 0; }' > have_lzma.c && $(CC) $(FLAGS) -o have_lzma$(EXT) have_lzma.c -llzma 2> $(VOID) && rm have_lzma$(EXT) && echo 1 || echo 0; rm have_lzma.c) ifeq ($(HAVE_LZMA), 1) LZMA_MSG := ==> building zstd with .xz/.lzma compression support LZMACPP = -DZSTD_LZMACOMPRESS -DZSTD_LZMADECOMPRESS @@ -130,7 +133,7 @@ endif # lz4 detection NO_LZ4_MSG := ==> no liblz4, building zstd without .lz4 support -HAVE_LZ4 := $(shell printf '\#include \n\#include \nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c) +HAVE_LZ4 := $(shell printf '$(NUM_SYMBOL)include \n\#include \nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c) ifeq ($(HAVE_LZ4), 1) LZ4_MSG := ==> building zstd with .lz4 compression support LZ4CPP = -DZSTD_LZ4COMPRESS -DZSTD_LZ4DECOMPRESS From 4de6b80c53ea75da2eaf0cc20e343445b10cc914 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 10 Feb 2020 12:36:56 -0800 Subject: [PATCH 198/402] Enable oss-fuzz CIFuzz dogfood --- .github/workflows/main.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000000..e40dd216abb --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,22 @@ +name: CIFuzz +on: [pull_request] +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + project-name: 'zstd' + dry-run: true + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + fuzz-time: 600 + dry-run: true + - name: Upload Crash + uses: actions/upload-artifact@v1 + if: failure() + with: + name: bug_report + path: ./out/bug_report \ No newline at end of file From f3414c92588aa0e28c02bc5395f35064a176181a Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 11 Feb 2020 10:43:15 -0800 Subject: [PATCH 199/402] [CIFuzz] Rename output path to artifacts --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e40dd216abb..bd602bcb5ad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,5 +18,5 @@ jobs: uses: actions/upload-artifact@v1 if: failure() with: - name: bug_report - path: ./out/bug_report \ No newline at end of file + name: artifacts + path: ./out/artifacts From cdd59c50e734c62dffb255d497b88c5d758a316c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ketelaars?= Date: Sat, 15 Feb 2020 12:42:00 +0100 Subject: [PATCH 200/402] Fix forgotten portable header prefix PR #1987 forgot to prefix another include causing lz4 detection to fail. --- programs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/Makefile b/programs/Makefile index a9ee3cb5311..47d3965cfca 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -133,7 +133,7 @@ endif # lz4 detection NO_LZ4_MSG := ==> no liblz4, building zstd without .lz4 support -HAVE_LZ4 := $(shell printf '$(NUM_SYMBOL)include \n\#include \nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c) +HAVE_LZ4 := $(shell printf '$(NUM_SYMBOL)include \n$(NUM_SYMBOL)include \nint main(void) { return 0; }' > have_lz4.c && $(CC) $(FLAGS) -o have_lz4$(EXT) have_lz4.c -llz4 2> $(VOID) && rm have_lz4$(EXT) && echo 1 || echo 0; rm have_lz4.c) ifeq ($(HAVE_LZ4), 1) LZ4_MSG := ==> building zstd with .lz4 compression support LZ4CPP = -DZSTD_LZ4COMPRESS -DZSTD_LZ4DECOMPRESS From 76c52b6b7c2c3b3343980dc53db256693188793d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Sun, 16 Feb 2020 11:31:17 -0500 Subject: [PATCH 201/402] Adding steps for setting up travis and appveyor (and some general notes) --- CONTRIBUTING.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd013f8084f..d8d0bc48703 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,56 @@ to do this once to work on any of Facebook's open source projects. Complete your CLA here: +## Setting up continuous integration (CI) on your fork +Zstd uses a number of different continuous integration (CI) tools to ensure that new changes +are well tested before they make it to an official release. Specifically, we use the platforms +travis-ci, circle-ci, and appveyor. + +Changes cannot be merged into the main dev branch unless they pass all of our CI tests. +The easiest way to run these CI tests on your own before submitting a PR to our dev branch +is to configure your personal fork of zstd with each of the CI platforms. Below, you'll find +instructions for doing this. + +### travis-ci +Follow these steps to link travis-ci with your github fork of zstd + +1. Make sure you are logged into your github account +2. Go to https://travis-ci.org/ +3. Click 'Sign in with Github' on the top right +4. Click 'Authorize travis-ci' +5. Click 'Activate all repositories using Github Apps' +6. Select 'Only select repositories' and select your fork of zstd from the drop down +7. Click 'Approve and Install' +8. Click 'Sign in with Github' again. This time, it will be for travis-pro (which will let you view your tests on the web dashboard) +9. Click 'Authorize travis-pro' +10. You should have travis set up on your fork now. + +### circle-ci +TODO + +### appveyor +Follow these steps to link circle-ci with your girhub fork of zstd + +1. Make sure you are logged into your github account +2. Go to https://www.appveyor.com/ +3. Click 'Sign in' on the top right +4. Select 'Github' on the left panel +5. Click 'Authorize appveyor' +6. You might be asked to select which repositories you want to give appveyor permission to. Select your fork of zstd if you're prompted +7. You should have appveyor set up on your fork now. + +### General notes on CI +CI tests run every time a pull request (PR) is created or updated. The exact tests +that get run will depend on the destination branch you specify. Some tests take +longer to run than others. Currently, our CI is set up to run a short +series of tests when creating a PR to the dev branch and a longer series of tests +when creating a PR to the master branch. You can look in the configuration files +of the respective CI platform for more information on what gets run when. + +Most people will just want to create a PR with the destination set to their local dev +branch of zstd. You can then find the status of the tests on the PR's page. You can also +re-run tests and cancel running tests from the PR page or from the respective CI's dashboard. + ## Issues We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. @@ -34,7 +84,7 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. In those cases, please go through the process outlined on that page and do not file a public issue. -## Coding Style +## Coding Style * 4 spaces for indentation rather than tabs ## License From e668c9b52896e1cf92c99da3b01e3bdbbae77100 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2020 10:50:38 -0500 Subject: [PATCH 202/402] Fix pkg-config File Generation Again Revises #1851. Fixes #1900. Replaces #1930. Thanks to @orbea, @neheb, @Polynomial-C, and particularly @eli-schwartz for pointing out the problem and suggesting solutions. Tested with ``` make -C lib clean libzstd.pc cat lib/libzstd.pc # should fail make -C lib clean libzstd.pc LIBDIR=/foo make -C lib clean libzstd.pc INCLUDEDIR=/foo make -C lib clean libzstd.pc LIBDIR=/usr/localfoo make -C lib clean libzstd.pc INCLUDEDIR=/usr/localfoo make -C lib clean libzstd.pc LIBDIR=/usr/local/lib prefix=/foo make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/include prefix=/foo # should succeed make -C lib clean libzstd.pc LIBDIR=/usr/local/foo make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/foo make -C lib clean libzstd.pc LIBDIR=/usr/local/ make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/ make -C lib clean libzstd.pc LIBDIR=/usr/local make -C lib clean libzstd.pc INCLUDEDIR=/usr/local make -C lib clean libzstd.pc LIBDIR=/tmp/foo prefix=/tmp make -C lib clean libzstd.pc INCLUDEDIR=/tmp/foo prefix=/tmp make -C lib clean libzstd.pc LIBDIR=/tmp/foo prefix=/tmp/foo make -C lib clean libzstd.pc INCLUDEDIR=/tmp/foo prefix=/tmp/foo # should also succeed make -C lib clean libzstd.pc prefix=/foo LIBDIR=/foo/bar INCLUDEDIR=/foo/ cat lib/libzstd.pc mkdir out cd out cmake ../build/cmake make cat lib/libzstd.pc ``` --- build/cmake/lib/CMakeLists.txt | 5 +++-- lib/Makefile | 14 ++++++++++++-- lib/libzstd.pc.in | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index e92647bf186..29ff57aa0f6 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -134,11 +134,12 @@ endif () if (UNIX) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") - set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") + set(LIBDIR "${CMAKE_INSTALL_LIBDIR}") + set(INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") add_custom_target(libzstd.pc ALL ${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc" - -DPREFIX="${PREFIX}" -DVERSION="${VERSION}" + -DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}" -P "${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig.cmake" COMMENT "Creating pkg-config file") diff --git a/lib/Makefile b/lib/Makefile index fd1710cf1a0..dbd64994c83 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -224,6 +224,16 @@ LIBDIR ?= $(libdir) includedir ?= $(PREFIX)/include INCLUDEDIR ?= $(includedir) +PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -e "s@^$(exec_prefix)\\(/\\|$$\\)@@p") +PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -e "s@^$(prefix)\\(/\\|$$\\)@@p") + +ifeq (,$(shell echo "$(LIBDIR)" | sed -n -e "\\@^$(exec_prefix)\\(/\\|$$\\)@ p")) +$(error configured libdir ($(LIBDIR)) is outside of prefix ($(prefix)), can't generate pkg-config file) +endif +ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -e "\\@^$(prefix)\\(/\\|$$\\)@ p")) +$(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(exec_prefix)), can't generate pkg-config file) +endif + ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly)) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig else @@ -239,11 +249,11 @@ endif INSTALL_PROGRAM ?= $(INSTALL) INSTALL_DATA ?= $(INSTALL) -m 644 - -libzstd.pc: libzstd.pc: libzstd.pc.in @echo creating pkgconfig @sed -e 's|@PREFIX@|$(PREFIX)|' \ + -e 's|@LIBDIR@|$(PCLIBDIR)|' \ + -e 's|@INCLUDEDIR@|$(PCINCDIR)|' \ -e 's|@VERSION@|$(VERSION)|' \ $< >$@ diff --git a/lib/libzstd.pc.in b/lib/libzstd.pc.in index e7880be475d..8ec0235ad9b 100644 --- a/lib/libzstd.pc.in +++ b/lib/libzstd.pc.in @@ -4,8 +4,8 @@ prefix=@PREFIX@ exec_prefix=${prefix} -includedir=${prefix}/include -libdir=${exec_prefix}/lib +includedir=${prefix}/@INCLUDEDIR@ +libdir=${exec_prefix}/@LIBDIR@ Name: zstd Description: fast lossless compression algorithm library From 73737231b95976f24b7b9bff96240976b11dcce0 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2020 13:17:17 -0500 Subject: [PATCH 203/402] Allow Manual Overriding of pkg-config Lib and Include Dirs When the `PCLIBDIR` or `PCINCDIR` is non-empty (either because we succeeded in removing the prefix, or because it was manually set), we don't need to perform the check. This lets us trust users who go to the trouble of setting a manual override, rather than still blindly failing the make. They'll still be prefixed with `${prefix}/` / `${exec_prefix}/` in the pkg-config file though. --- lib/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/Makefile b/lib/Makefile index dbd64994c83..b067c11a2e5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -227,12 +227,21 @@ INCLUDEDIR ?= $(includedir) PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -e "s@^$(exec_prefix)\\(/\\|$$\\)@@p") PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -e "s@^$(prefix)\\(/\\|$$\\)@@p") +ifeq (,$(PCLIBDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCLIBDIR ifeq (,$(shell echo "$(LIBDIR)" | sed -n -e "\\@^$(exec_prefix)\\(/\\|$$\\)@ p")) $(error configured libdir ($(LIBDIR)) is outside of prefix ($(prefix)), can't generate pkg-config file) endif +endif + +ifeq (,$(PCINCDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCINCDIR ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -e "\\@^$(prefix)\\(/\\|$$\\)@ p")) $(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(exec_prefix)), can't generate pkg-config file) endif +endif ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly)) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig From e5ef935cf6160768e20cd73db3d9450aa8b7f8cf Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 18 Feb 2020 13:40:58 -0500 Subject: [PATCH 204/402] Fix Variable Capitalization --- lib/Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index b067c11a2e5..db35207bb6f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -219,27 +219,28 @@ DESTDIR ?= prefix ?= /usr/local PREFIX ?= $(prefix) exec_prefix ?= $(PREFIX) -libdir ?= $(exec_prefix)/lib +EXEC_PREFIX ?= $(exec_prefix) +libdir ?= $(EXEC_PREFIX)/lib LIBDIR ?= $(libdir) includedir ?= $(PREFIX)/include INCLUDEDIR ?= $(includedir) -PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -e "s@^$(exec_prefix)\\(/\\|$$\\)@@p") -PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -e "s@^$(prefix)\\(/\\|$$\\)@@p") +PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -e "s@^$(EXEC_PREFIX)\\(/\\|$$\\)@@p") +PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -e "s@^$(PREFIX)\\(/\\|$$\\)@@p") ifeq (,$(PCLIBDIR)) # Additional prefix check is required, since the empty string is technically a # valid PCLIBDIR -ifeq (,$(shell echo "$(LIBDIR)" | sed -n -e "\\@^$(exec_prefix)\\(/\\|$$\\)@ p")) -$(error configured libdir ($(LIBDIR)) is outside of prefix ($(prefix)), can't generate pkg-config file) +ifeq (,$(shell echo "$(LIBDIR)" | sed -n -e "\\@^$(EXEC_PREFIX)\\(/\\|$$\\)@ p")) +$(error configured libdir ($(LIBDIR)) is outside of prefix ($(PREFIX)), can't generate pkg-config file) endif endif ifeq (,$(PCINCDIR)) # Additional prefix check is required, since the empty string is technically a # valid PCINCDIR -ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -e "\\@^$(prefix)\\(/\\|$$\\)@ p")) -$(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(exec_prefix)), can't generate pkg-config file) +ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -e "\\@^$(PREFIX)\\(/\\|$$\\)@ p")) +$(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(EXEC_PREFIX)), can't generate pkg-config file) endif endif From 042b28bd2c1b4c0e76f6c97ec9661324fd7b72b2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 18 Feb 2020 13:03:52 -0800 Subject: [PATCH 205/402] Outlining our current workflow --- CONTRIBUTING.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d8d0bc48703..e72ec9270a9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,89 @@ to do this once to work on any of Facebook's open source projects. Complete your CLA here: +## Workflow +Zstd uses a branch-based workflow for making changes to the codebase. Typically, zstd +will use a new branch per sizable topic. For smaller changes, it is okay to lump multiple +related changes into a branch. + +Our contribution process works in three main stages: +1. Local development + * Update: + * Checkout your fork of zstd if you have not already + ``` + git checkout https://github.com//zstd + cd zstd + ``` + * Update your local dev branch + ``` + git pull https://github.com/facebook/zstd dev + git push origin dev + ``` + * Topic and deveopment: + * Make a new branch on your fork about the topic you're developing for + ``` + # branch names should be consise but sufficiently informative + git checkout -b + git push origin + ``` + * Make commits and push + ``` + # make some changes = + git add -u && git commit -m + git push origin + ``` + * Note: run local tests to ensure that your changes didn't break existing functionality + * Quick check + ``` + make shortest + ``` + * Longer check + ``` + make test + ``` +2. Code Review and CI tests + * Ensure CI tests pass: + * Before sharing anything to the community, make sure that all CI tests pass on your local fork. + See our section on setting up your CI environment for more information on how to do this. + * Create a pull request: + * When you are ready to share you changes to the community, create a pull request from your branch + to facebook:dev. You can do this very easily by clicking 'Create Pull Request' on your fork's home + page. + * From there, select the branch where you made changes as your source branch and facebook:dev + as the destination. + * Examine the diff presented between the two branches to make sure there is nothing unexpected. + * Write a good pull request description: + * While there is no strict template that our contributers follow, we would like them to + sufficiently summarize and motivate the changes they are proposing. We recommend all pull requests, + at least indirectly, address the following points. + * Is this pull request important and why? + * Is it addressing an issue? If so, what issue? (provide links for convenience please) + * Is this a new feature? If so, why is it useful and/or necessary? + * Are there background references and documents that reviewers should be aware of to properly assess this change? + * Note: make sure to point out any design and architectural decisions that you made and the rationale behind them. + * Note: if you have been working with a specific user and would like them to review your work, make sure you mention them using (@) + * Submit the pull request and iterate with feedback. +3. Merge and Release + * Getting approval: + * You will have to iterate on your changes with feedback from other collaborators to reach a point + where your pull request can be safely merged. + * To avoid too many comments on style and convention, make sure that you have a + look at your style section below before creating a pull request. + * Eventually, someone from the zstd team will approve your pull request and not long after merge it into + the dev branch. + * Housekeeping: + * Most PRs are linked with one or more Github issues. If this is the case for your PR, make sure + the corresponding issue is mentioned. If your change 'fixes' or completely addresses the + issue at hand, then please indicate this by requesting that an issue be closed by commenting. + * Just because your changes have been merged does not mean the topic or larger issue is complete. Remember + that the change must make it to an official zstd release for it to be meaningful. We recommend + that contributers track the activity on their pull request and corresponding issue(s) page(s) until + their change makes it to the next release of zstd. Users will often discover bugs in your code or + suggest ways to refine and improve your initial changes even after the pull request is merged. + +## Zstandard style and conventions + + ## Setting up continuous integration (CI) on your fork Zstd uses a number of different continuous integration (CI) tools to ensure that new changes are well tested before they make it to an official release. Specifically, we use the platforms From 8f8c53d995583600886957e1942f388360bd808f Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 18 Feb 2020 14:21:19 -0800 Subject: [PATCH 206/402] Remove redundant section and typo --- CONTRIBUTING.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e72ec9270a9..02834659c62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,7 +93,7 @@ Our contribution process works in three main stages: * You will have to iterate on your changes with feedback from other collaborators to reach a point where your pull request can be safely merged. * To avoid too many comments on style and convention, make sure that you have a - look at your style section below before creating a pull request. + look at our style section below before creating a pull request. * Eventually, someone from the zstd team will approve your pull request and not long after merge it into the dev branch. * Housekeeping: @@ -106,9 +106,6 @@ Our contribution process works in three main stages: their change makes it to the next release of zstd. Users will often discover bugs in your code or suggest ways to refine and improve your initial changes even after the pull request is merged. -## Zstandard style and conventions - - ## Setting up continuous integration (CI) on your fork Zstd uses a number of different continuous integration (CI) tools to ensure that new changes are well tested before they make it to an official release. Specifically, we use the platforms From 4e728e26ca6a8b10404d733b4892c31d97677689 Mon Sep 17 00:00:00 2001 From: Philip Jones Date: Tue, 18 Feb 2020 15:30:59 -0800 Subject: [PATCH 207/402] Fix integer parsing in cli (#2003) --- programs/zstdcli.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 3ebecadcab2..ce431e6c9ed 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -254,10 +254,12 @@ static int readU32FromCharChecked(const char** stringPtr, unsigned* value) { unsigned result = 0; while ((**stringPtr >='0') && (**stringPtr <='9')) { - unsigned const max = (((unsigned)(-1)) / 10) - 1; + unsigned const max = ((unsigned)(-1)) / 10; + unsigned last = result; if (result > max) return 1; /* overflow error */ result *= 10; result += (unsigned)(**stringPtr - '0'); + if (result < last) return 1; /* overflow error */ (*stringPtr)++ ; } if ((**stringPtr=='K') || (**stringPtr=='M')) { From 834d06b655e514b35af09862ca303d47bfb89b4e Mon Sep 17 00:00:00 2001 From: Lehman Garrison Date: Thu, 20 Feb 2020 14:29:58 -0500 Subject: [PATCH 208/402] Allow some cli options to accept numeric values up to size_t instead of unsigned int --- programs/zstdcli.c | 55 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index ce431e6c9ed..5b14cb58018 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -284,12 +284,57 @@ static int readU32FromCharChecked(const char** stringPtr, unsigned* value) * Will also modify `*stringPtr`, advancing it to position where it stopped reading. * Note : function will exit() program if digit sequence overflows */ static unsigned readU32FromChar(const char** stringPtr) { - static const char errorMsg[] = "error: numeric value too large"; + static const char errorMsg[] = "error: numeric value overflows 32-bit unsigned int"; unsigned result; if (readU32FromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } return result; } +/*! readSizeTFromCharChecked() : + * @return 0 if success, and store the result in *value. + * allows and interprets K, KB, KiB, M, MB and MiB suffix. + * Will also modify `*stringPtr`, advancing it to position where it stopped reading. + * @return 1 if an overflow error occurs */ +static int readSizeTFromCharChecked(const char** stringPtr, size_t* value) +{ + size_t result = 0; + while ((**stringPtr >='0') && (**stringPtr <='9')) { + size_t const max = ((size_t)(-1)) / 10; + size_t last = result; + if (result > max) return 1; /* overflow error */ + result *= 10; + result += (size_t)(**stringPtr - '0'); + if (result < last) return 1; /* overflow error */ + (*stringPtr)++ ; + } + if ((**stringPtr=='K') || (**stringPtr=='M')) { + size_t const maxK = ((size_t)(-1)) >> 10; + if (result > maxK) return 1; /* overflow error */ + result <<= 10; + if (**stringPtr=='M') { + if (result > maxK) return 1; /* overflow error */ + result <<= 10; + } + (*stringPtr)++; /* skip `K` or `M` */ + if (**stringPtr=='i') (*stringPtr)++; + if (**stringPtr=='B') (*stringPtr)++; + } + *value = result; + return 0; +} + +/*! readSizeTFromChar() : + * @return : size_t value read from input in `char` format. + * allows and interprets K, KB, KiB, M, MB and MiB suffix. + * Will also modify `*stringPtr`, advancing it to position where it stopped reading. + * Note : function will exit() program if digit sequence overflows */ +static size_t readSizeTFromChar(const char** stringPtr) { + static const char errorMsg[] = "error: numeric value overflows size_t"; + size_t result; + if (readSizeTFromCharChecked(stringPtr, &result)) { errorOut(errorMsg); } + return result; +} + /** longCommandWArg() : * check if *stringPtr is the same as longCommand. * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. @@ -762,13 +807,13 @@ int main(int const argCount, const char* argv[]) if (longCommandWArg(&argument, "--memlimit=")) { memLimit = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--memory=")) { memLimit = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--memlimit-decompress=")) { memLimit = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "--block-size=")) { blockSize = readU32FromChar(&argument); continue; } + if (longCommandWArg(&argument, "--block-size=")) { blockSize = readSizeTFromChar(&argument); continue; } if (longCommandWArg(&argument, "--maxdict=")) { maxDictSize = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--dictID=")) { dictID = readU32FromChar(&argument); continue; } if (longCommandWArg(&argument, "--zstd=")) { if (!parseCompressionParameters(argument, &compressionParams)) { badusage(programName); CLEAN_RETURN(1); } continue; } - if (longCommandWArg(&argument, "--stream-size=")) { streamSrcSize = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readU32FromChar(&argument); continue; } - if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readU32FromChar(&argument); continue; } + if (longCommandWArg(&argument, "--stream-size=")) { streamSrcSize = readSizeTFromChar(&argument); continue; } + if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readSizeTFromChar(&argument); continue; } + if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readSizeTFromChar(&argument); continue; } if (longCommandWArg(&argument, "--output-dir-flat=")) { outDirName = argument; continue; } if (longCommandWArg(&argument, "--patch-from=")) { patchFromDictFileName = argument; continue; } if (longCommandWArg(&argument, "--long")) { From 0c4ee510d5b9943748cd149978c2fce8793f6cc7 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 24 Feb 2020 12:36:19 -0800 Subject: [PATCH 209/402] Update CIFuzz file and turn off dry-run mode --- .github/workflows/main.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bd602bcb5ad..9309ba92f26 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,13 +7,14 @@ jobs: - name: Build Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: - project-name: 'zstd' - dry-run: true + oss-fuzz-project-name: 'zstd' + dry-run: false - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: - fuzz-time: 600 - dry-run: true + oss-fuzz-project-name: 'zstd' + fuzz-seconds: 600 + dry-run: false - name: Upload Crash uses: actions/upload-artifact@v1 if: failure() From b669c5347a1c745c3f798e9160402cfedc3edbaa Mon Sep 17 00:00:00 2001 From: Felix Handte Date: Wed, 26 Feb 2020 10:52:49 -0800 Subject: [PATCH 210/402] Revert "Fix pkg-config File Generation Again" (#2016) --- build/cmake/lib/CMakeLists.txt | 5 ++--- lib/Makefile | 26 +++----------------------- lib/libzstd.pc.in | 4 ++-- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 29ff57aa0f6..e92647bf186 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -134,12 +134,11 @@ endif () if (UNIX) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") - set(LIBDIR "${CMAKE_INSTALL_LIBDIR}") - set(INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") + set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") add_custom_target(libzstd.pc ALL ${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc" - -DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}" + -DPREFIX="${PREFIX}" -DVERSION="${VERSION}" -P "${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig.cmake" COMMENT "Creating pkg-config file") diff --git a/lib/Makefile b/lib/Makefile index db35207bb6f..fd1710cf1a0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -219,31 +219,11 @@ DESTDIR ?= prefix ?= /usr/local PREFIX ?= $(prefix) exec_prefix ?= $(PREFIX) -EXEC_PREFIX ?= $(exec_prefix) -libdir ?= $(EXEC_PREFIX)/lib +libdir ?= $(exec_prefix)/lib LIBDIR ?= $(libdir) includedir ?= $(PREFIX)/include INCLUDEDIR ?= $(includedir) -PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -e "s@^$(EXEC_PREFIX)\\(/\\|$$\\)@@p") -PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -e "s@^$(PREFIX)\\(/\\|$$\\)@@p") - -ifeq (,$(PCLIBDIR)) -# Additional prefix check is required, since the empty string is technically a -# valid PCLIBDIR -ifeq (,$(shell echo "$(LIBDIR)" | sed -n -e "\\@^$(EXEC_PREFIX)\\(/\\|$$\\)@ p")) -$(error configured libdir ($(LIBDIR)) is outside of prefix ($(PREFIX)), can't generate pkg-config file) -endif -endif - -ifeq (,$(PCINCDIR)) -# Additional prefix check is required, since the empty string is technically a -# valid PCINCDIR -ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -e "\\@^$(PREFIX)\\(/\\|$$\\)@ p")) -$(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(EXEC_PREFIX)), can't generate pkg-config file) -endif -endif - ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly)) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig else @@ -259,11 +239,11 @@ endif INSTALL_PROGRAM ?= $(INSTALL) INSTALL_DATA ?= $(INSTALL) -m 644 + +libzstd.pc: libzstd.pc: libzstd.pc.in @echo creating pkgconfig @sed -e 's|@PREFIX@|$(PREFIX)|' \ - -e 's|@LIBDIR@|$(PCLIBDIR)|' \ - -e 's|@INCLUDEDIR@|$(PCINCDIR)|' \ -e 's|@VERSION@|$(VERSION)|' \ $< >$@ diff --git a/lib/libzstd.pc.in b/lib/libzstd.pc.in index 8ec0235ad9b..e7880be475d 100644 --- a/lib/libzstd.pc.in +++ b/lib/libzstd.pc.in @@ -4,8 +4,8 @@ prefix=@PREFIX@ exec_prefix=${prefix} -includedir=${prefix}/@INCLUDEDIR@ -libdir=${exec_prefix}/@LIBDIR@ +includedir=${prefix}/include +libdir=${exec_prefix}/lib Name: zstd Description: fast lossless compression algorithm library From d2464776d146fb2f80368393f245d394eb1d187b Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 26 Feb 2020 14:29:30 -0800 Subject: [PATCH 211/402] man page : added `--verbose` long command also updated `zstd.1` stacking prior updates completed on `zstd.1.md`. --- programs/zstd.1 | 31 +++++++++++++++++++++++-------- programs/zstd.1.md | 2 +- programs/zstdgrep.1 | 2 +- programs/zstdless.1 | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/programs/zstd.1 b/programs/zstd.1 index 1ff655d173d..4d146034e8d 100644 --- a/programs/zstd.1 +++ b/programs/zstd.1 @@ -1,5 +1,5 @@ . -.TH "ZSTD" "1" "November 2019" "zstd 1.4.4" "User Commands" +.TH "ZSTD" "1" "February 2020" "zstd 1.4.5" "User Commands" . .SH "NAME" \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files @@ -111,6 +111,18 @@ Display information related to a zstd compressed file, such as size, ratio, and Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \fB\-\-memory=windowSize\fR needs to be passed to the decompressor\. . .IP "\(bu" 4 +\fB\-\-patch\-from=FILE\fR: Specify the file to be used as a reference point for zstd\'s diff engine\. This is effectively dictionary compression with some convenient parameter selection, namely that windowSize > srcSize\. +. +.IP +Note: cannot use both this and \-D together +. +.IP "\(bu" 4 +\fB\-M#\fR, \fB\-\-memory=#\fR: Set a memory usage limit\. By default, Zstandard uses 128 MB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (ie\. you can increase or decrease it)\. +. +.IP +This is also used during compression when using with \-\-patch\-from=\. In this case, this parameter overrides that maximum size allowed for a dictionary\. (128 MB)\. +. +.IP "\(bu" 4 \fB\-T#\fR, \fB\-\-threads=#\fR: Compress using \fB#\fR working threads (default: 1)\. If \fB#\fR is 0, attempt to detect and use the number of physical CPU cores\. In all cases, the nb of threads is capped to ZSTDMT_NBTHREADS_MAX==200\. This modifier does nothing if \fBzstd\fR is compiled without multithread support\. . .IP "\(bu" 4 @@ -171,7 +183,10 @@ Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \ \fB\-V\fR, \fB\-\-version\fR: display version number and exit\. Advanced : \fB\-vV\fR also displays supported formats\. \fB\-vvV\fR also displays POSIX support\. . .IP "\(bu" 4 -\fB\-v\fR: verbose mode +\fB\-v\fR, \fB\-\-verbose\fR: verbose mode +. +.IP "\(bu" 4 +\fB\-\-show\-default\-cparams\fR: Shows the default compresssion parameters that will be used for a particular src file\. If the provided src file is not a regular file (eg\. named pipe), the cli will just output the default paramters\. That is, the parameters that are used when the src size is unknown\. . .IP "\(bu" 4 \fB\-q\fR, \fB\-\-quiet\fR: suppress warnings, interactivity, and notifications\. specify twice to suppress errors too\. @@ -338,7 +353,7 @@ Specify the maximum number of bits for a hash table\. Bigger hash tables cause less collisions which usually makes compression faster, but requires more memory during compression\. . .IP -The minimum \fIhlog\fR is 6 (64 B) and the maximum is 26 (128 MiB)\. +The minimum \fIhlog\fR is 6 (64 B) and the maximum is 30 (1 GiB)\. . .TP \fBchainLog\fR=\fIclog\fR, \fBclog\fR=\fIclog\fR @@ -348,7 +363,7 @@ Specify the maximum number of bits for a hash chain or a binary tree\. Higher numbers of bits increases the chance to find a match which usually improves compression ratio\. It also slows down compression speed and increases memory requirements for compression\. This option is ignored for the ZSTD_fast strategy\. . .IP -The minimum \fIclog\fR is 6 (64 B) and the maximum is 28 (256 MiB)\. +The minimum \fIclog\fR is 6 (64 B) and the maximum is 29 (524 Mib) on 32\-bit platforms and 30 (1 Gib) on 64\-bit platforms\. . .TP \fBsearchLog\fR=\fIslog\fR, \fBslog\fR=\fIslog\fR @@ -358,7 +373,7 @@ Specify the maximum number of searches in a hash chain or a binary tree using lo More searches increases the chance to find a match which usually increases compression ratio but decreases compression speed\. . .IP -The minimum \fIslog\fR is 1 and the maximum is 26\. +The minimum \fIslog\fR is 1 and the maximum is \'windowLog\' \- 1\. . .TP \fBminMatch\fR=\fImml\fR, \fBmml\fR=\fImml\fR @@ -384,7 +399,7 @@ For ZSTD_fast, it triggers ultra\-fast mode when > 0\. The value represents the For all other strategies, this field has no impact\. . .IP -The minimum \fItlen\fR is 0 and the maximum is 999\. +The minimum \fItlen\fR is 0 and the maximum is 128 Kib\. . .TP \fBoverlapLog\fR=\fIovlog\fR, \fBovlog\fR=\fIovlog\fR @@ -404,7 +419,7 @@ This option is ignored unless long distance matching is enabled\. Bigger hash tables usually improve compression ratio at the expense of more memory during compression and a decrease in compression speed\. . .IP -The minimum \fIlhlog\fR is 6 and the maximum is 26 (default: 20)\. +The minimum \fIlhlog\fR is 6 and the maximum is 30 (default: 20)\. . .TP \fBldmMinMatch\fR=\fIlmml\fR, \fBlmml\fR=\fIlmml\fR @@ -430,7 +445,7 @@ This option is ignored unless long distance matching is enabled\. Larger bucket sizes improve collision resolution but decrease compression speed\. . .IP -The minimum \fIlblog\fR is 0 and the maximum is 8 (default: 3)\. +The minimum \fIlblog\fR is 1 and the maximum is 8 (default: 3)\. . .TP \fBldmHashRateLog\fR=\fIlhrlog\fR, \fBlhrlog\fR=\fIlhrlog\fR diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 5b6505ba29d..dc6e9b5d2d4 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -226,7 +226,7 @@ the last one takes effect. display version number and exit. Advanced : `-vV` also displays supported formats. `-vvV` also displays POSIX support. -* `-v`: +* `-v`, `--verbose`: verbose mode * `--show-default-cparams`: Shows the default compresssion parameters that will be used for a diff --git a/programs/zstdgrep.1 b/programs/zstdgrep.1 index b97f8cabcc0..5718e998e25 100644 --- a/programs/zstdgrep.1 +++ b/programs/zstdgrep.1 @@ -1,5 +1,5 @@ . -.TH "ZSTDGREP" "1" "October 2019" "zstd 1.4.4" "User Commands" +.TH "ZSTDGREP" "1" "February 2020" "zstd 1.4.5" "User Commands" . .SH "NAME" \fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files diff --git a/programs/zstdless.1 b/programs/zstdless.1 index 1ecc8bdc531..b06a4bc18fd 100644 --- a/programs/zstdless.1 +++ b/programs/zstdless.1 @@ -1,5 +1,5 @@ . -.TH "ZSTDLESS" "1" "October 2019" "zstd 1.4.4" "User Commands" +.TH "ZSTDLESS" "1" "February 2020" "zstd 1.4.5" "User Commands" . .SH "NAME" \fBzstdless\fR \- view zstandard\-compressed files From 0a00397e19adcc3b474e865ef0bf838b74d5f6f5 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 27 Feb 2020 13:53:03 -0800 Subject: [PATCH 212/402] [cirrus-ci] Removing pkg -y update and using 11.3-snap instead of 11.2 (#2018) * Replacing with boilerplate from cirrus * Adding task name and adding back freebsd 11.x * Changing from 11.3 to freebsd-11-3-snap * Rearanging the order of matrix and instance --- .cirrus.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 506647a009e..8387ca1b1a5 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,16 +1,11 @@ -env: - CIRRUS_CLONE_DEPTH: 1 - ARCH: amd64 - task: + name: FreeBSD (shortest) freebsd_instance: matrix: - image: freebsd-12-0-release-amd64 - image: freebsd-11-2-release-amd64 - install_script: - - sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf - - pkg upgrade -y - - pkg install -y gmake coreutils + image_family: freebsd-12-1 + # The stable 11.3 image causes "Agent is not responding" so use a snapshot + image_family: freebsd-11-3-snap + install_script: pkg install -y gmake coreutils script: | MOREFLAGS="-Werror" gmake -j all gmake shortest From 23165b387e5a10029ed58b165a8e173d141e4612 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 27 Feb 2020 13:56:56 -0800 Subject: [PATCH 213/402] Adding hashLog to --show-default-cparams --- programs/zstdcli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 5b14cb58018..b7f068ac1c9 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1289,6 +1289,7 @@ int main(int const argCount, const char* argv[]) else DISPLAY("%s (src size unknown)\n", filenames->fileNames[fileNb]); DISPLAY(" - windowLog : %u\n", cParams.windowLog); DISPLAY(" - chainLog : %u\n", cParams.chainLog); + DISPLAY(" - hashLog : %u\n", cParams.hashLog); DISPLAY(" - searchLog : %u\n", cParams.searchLog); DISPLAY(" - minMatch : %u\n", cParams.minMatch); DISPLAY(" - targetLength : %u\n", cParams.targetLength); From c836992be17be85df107964f447022ffbd9c3519 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 2 Mar 2020 11:13:04 -0800 Subject: [PATCH 214/402] Dont log errors when ZSTD_fseBitCost() returns an error --- lib/compress/zstd_compress_sequences.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index 950471c45f9..b69221e63b2 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -96,17 +96,21 @@ size_t ZSTD_fseBitCost( unsigned s; FSE_CState_t cstate; FSE_initCState(&cstate, ctable); - RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC, - "Repeat FSE_CTable has maxSymbolValue %u < %u", + if (ZSTD_getFSEMaxSymbolValue(ctable) < max) { + DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u", ZSTD_getFSEMaxSymbolValue(ctable), max); + return ERROR(GENERIC); + } for (s = 0; s <= max; ++s) { unsigned const tableLog = cstate.stateLog; unsigned const badCost = (tableLog + 1) << kAccuracyLog; unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog); if (count[s] == 0) continue; - RETURN_ERROR_IF(bitCost >= badCost, GENERIC, - "Repeat FSE_CTable has Prob[%u] == 0", s); + if (bitCost >= badCost) { + DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s); + return ERROR(GENERIC); + } cost += count[s] * bitCost; } return cost >> kAccuracyLog; From 2c10bbd8666bb9944ff9c9a1adb5bfbced67e41e Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 2 Mar 2020 11:25:36 -0800 Subject: [PATCH 215/402] [zstdgrep] Log zstd decompression errors to stderr --- programs/zstdgrep | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/zstdgrep b/programs/zstdgrep index 4879fb0dae4..cd6ed549569 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -109,7 +109,7 @@ if [ "$#" -lt 1 ]; then # ... on stdin set -f # Disable file name generation (globbing). # shellcheck disable=SC2086 - "${zcat}" -fq - | "${grep}" ${grep_args} -- "${pattern}" - + "${zcat}" -f - | "${grep}" ${grep_args} -- "${pattern}" - EXIT_CODE=$? set +f else @@ -121,9 +121,9 @@ else while [ "$#" -gt 0 ]; do # shellcheck disable=SC2086 if [ $pattern_found -eq 2 ]; then - "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - + "${zcat}" -f -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - else - "${zcat}" -fq -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - + "${zcat}" -f -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - fi [ "$?" -ne 0 ] && EXIT_CODE=1 shift From f589e2b5c8fc79fd07a82cb0431ff9851c0dd0bc Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 2 Mar 2020 11:30:12 -0800 Subject: [PATCH 216/402] [zstdgrep] Remove -f because zstdcat implies it --- programs/zstdgrep | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/zstdgrep b/programs/zstdgrep index cd6ed549569..61efaa9474a 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -109,7 +109,7 @@ if [ "$#" -lt 1 ]; then # ... on stdin set -f # Disable file name generation (globbing). # shellcheck disable=SC2086 - "${zcat}" -f - | "${grep}" ${grep_args} -- "${pattern}" - + "${zcat}" - | "${grep}" ${grep_args} -- "${pattern}" - EXIT_CODE=$? set +f else @@ -121,9 +121,9 @@ else while [ "$#" -gt 0 ]; do # shellcheck disable=SC2086 if [ $pattern_found -eq 2 ]; then - "${zcat}" -f -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - + "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - else - "${zcat}" -f -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - + "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - fi [ "$?" -ne 0 ] && EXIT_CODE=1 shift From dbd6439bb6b2fac5a690ca825545888e123c045f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 2 Mar 2020 13:04:37 -0800 Subject: [PATCH 217/402] [zstdgrep] Add a simple test --- tests/playTests.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/playTests.sh b/tests/playTests.sh index 09fe92fcf9a..c7605cc480f 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -63,6 +63,7 @@ SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) PRGDIR="$SCRIPT_DIR/../programs" TESTDIR="$SCRIPT_DIR/../tests" UNAME=$(uname) +ZSTDGREP="$PRGDIR/zstdgrep" detectedTerminal=false if [ -t 0 ] && [ -t 1 ] @@ -225,6 +226,17 @@ $ZSTD tmp -c --compress-literals -19 | $ZSTD -t $ZSTD -b --fast=1 -i0e1 tmp --compress-literals $ZSTD -b --fast=1 -i0e1 tmp --no-compress-literals +println "\n===> zstdgrep tests" +ln -sf $ZSTD_BIN zstdcat +rm -f tmp_grep +echo "1234" > tmp_grep +$ZSTD -f tmp_grep +lines=$(ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep tmp_grep.zst | wc -l) +test 2 -eq $lines +ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst && die "Should have failed" +ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst | grep "No such file or directory" || true +rm -f tmp_grep* + println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir From cba46e9b7b3702e76073fe6c24ff490d17630a50 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 3 Mar 2020 13:12:02 -0800 Subject: [PATCH 218/402] Fixing ZSTD_c_compressionLevel confusing note --- lib/zstd.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/zstd.h b/lib/zstd.h index 73cb3d315d0..fcd50986415 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -274,7 +274,10 @@ typedef enum { * Default level is ZSTD_CLEVEL_DEFAULT==3. * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. * Note 1 : it's possible to pass a negative compression level. - * Note 2 : setting a level resets all other compression parameters to default */ + * Note 2 : setting a level does not automatically set all other compression parameters + * to default. Setting this will however eventually dynamically impact the compression + * parameters which have not been manually set. The manually set + * ones will 'stick'. */ /* Advanced compression parameters : * It's possible to pin down compression parameters to some specific values. * In which case, these values are no longer dynamically selected by the compressor */ From bd6a145e8bf420026fa96c3755464f3208ba1d6b Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 3 Mar 2020 14:57:02 -0800 Subject: [PATCH 219/402] Add issue templates to zstd LZ4 just added this. I think it would be helpful here too. --- .github/ISSUE_TEMPLATE/bug_report.md | 35 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..bacdac27b06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Downloads data '...' +2. Run '...' with flags '...' +3. Scroll up on the log to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots and charts** +If applicable, add screenshots and charts to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. Mac] + - Version [e.g. 22] + - Compiler [e.g gcc] + - Flags [e.g O2] + - Other relevant hardware specs [e.g. Dual-core] + - Build system [e.g. Makefile] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..bbcbbe7d615 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 1bc56dfa4c8443ce193c1196c9176f9668a4ab09 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 3 Mar 2020 15:22:35 -0800 Subject: [PATCH 220/402] Adding icc make check to travis ci --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.travis.yml b/.travis.yml index 282e0e7d642..b8a0244a568 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,23 @@ env: matrix: fast_finish: true include: + - name: icc + compiler: icc + env: + - C_COMPILER=icc + - CXX_COMPILER=icpc + - COMPILER_FLAGS='-wd13200 -wd13203' + install: + - source /opt/intel/inteloneapi/compiler/latest/env/vars.sh + addons: + apt: + sources: + - sourceline: 'deb https://apt.repos.intel.com/oneapi all main' + key_url: 'https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB' + packages: + - intel-oneapi-icc + script: make check + - name: arm64 # ~2.5 mn os: linux arch: arm64 From c7060bb7116eec55de9536f4670604e6731dc9ae Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 3 Mar 2020 15:46:11 -0800 Subject: [PATCH 221/402] Removing mmx compiler flags --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b8a0244a568..77227c3648f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,6 @@ matrix: env: - C_COMPILER=icc - CXX_COMPILER=icpc - - COMPILER_FLAGS='-wd13200 -wd13203' install: - source /opt/intel/inteloneapi/compiler/latest/env/vars.sh addons: From 5f49578be7f0d21b4a6c734f9b827d7cbad2b7c1 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 4 Mar 2020 16:12:16 -0800 Subject: [PATCH 222/402] [opt] Don't recompute initial literals price --- lib/compress/zstd_opt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 2e50fca6ff5..44a13ddb778 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -270,19 +270,6 @@ static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* con } } -/* ZSTD_literalsContribution() : - * creates a fake cost for the literals part of a sequence - * which can be compared to the ending cost of a match - * should a new match start at this position */ -static int ZSTD_literalsContribution(const BYTE* const literals, U32 const litLength, - const optState_t* const optPtr, - int optLevel) -{ - int const contribution = (int)ZSTD_rawLiteralsCost(literals, litLength, optPtr, optLevel) - + ZSTD_litLengthContribution(litLength, optPtr, optLevel); - return contribution; -} - /* ZSTD_getMatchPrice() : * Provides the cost of the match part (offset + matchLength) of a sequence * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence. @@ -894,7 +881,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, { U32 i ; for (i=0; i immediate encoding */ { U32 const maxML = matches[nbMatches-1].len; From 610171ed86b947431796ec58854a673c674f6602 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 4 Mar 2020 16:29:19 -0800 Subject: [PATCH 223/402] [opt] Explain why we don't include literals price --- lib/compress/zstd_opt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 44a13ddb778..896365fc877 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -881,6 +881,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, { U32 i ; for (i=0; i immediate encoding */ From c6caa2d04ed505e78a3135e36ecfff7cc3a0306c Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 4 Mar 2020 16:35:26 -0800 Subject: [PATCH 224/402] [opt] Delete ZSTD_litLengthContribution --- lib/compress/zstd_opt.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 896365fc877..3caa4a1c31e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -249,27 +249,6 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP } } -/* ZSTD_litLengthContribution() : - * @return ( cost(litlength) - cost(0) ) - * this value can then be added to rawLiteralsCost() - * to provide a cost which is directly comparable to a match ending at same position */ -static int ZSTD_litLengthContribution(U32 const litLength, const optState_t* const optPtr, int optLevel) -{ - if (optPtr->priceType >= zop_predef) return (int)WEIGHT(litLength, optLevel); - - /* dynamic statistics */ - { U32 const llCode = ZSTD_LLcode(litLength); - int const contribution = (int)(LL_bits[llCode] * BITCOST_MULTIPLIER) - + (int)WEIGHT(optPtr->litLengthFreq[0], optLevel) /* note: log2litLengthSum cancel out */ - - (int)WEIGHT(optPtr->litLengthFreq[llCode], optLevel); -#if 1 - return contribution; -#else - return MAX(0, contribution); /* sometimes better, sometimes not ... */ -#endif - } -} - /* ZSTD_getMatchPrice() : * Provides the cost of the match part (offset + matchLength) of a sequence * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence. From 0f9882deb9d45b30e95c6eeeb0fac6b7354e4947 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 4 Mar 2020 17:23:00 -0800 Subject: [PATCH 225/402] [opt] Don't recompute repcodes while emitting sequences --- lib/compress/zstd_opt.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 3caa4a1c31e..fe44ebaf13e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1017,6 +1017,17 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ assert(opt[0].mlen == 0); + /* Set the next chunk's repcodes based on the repcodes of the beginning + * of the last match, and the last sequence. This avoids us having to + * update them while traversing the sequences. + */ + if (lastSequence.mlen != 0) { + repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0); + memcpy(rep, &reps, sizeof(reps)); + } else { + memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); + } + { U32 const storeEnd = cur + 1; U32 storeStart = storeEnd; U32 seqPos = cur; @@ -1053,20 +1064,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, continue; /* will finish */ } - /* repcodes update : like ZSTD_updateRep(), but update in place */ - if (offCode >= ZSTD_REP_NUM) { /* full offset */ - rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = offCode - ZSTD_REP_MOVE; - } else { /* repcode */ - U32 const repCode = offCode + (llen==0); - if (repCode) { /* note : if repCode==0, no change */ - U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - if (repCode >= 2) rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = currentOffset; - } } - assert(anchor + llen <= iend); ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen); ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH); @@ -1075,7 +1072,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } } ZSTD_setBasePrices(optStatePtr, optLevel); } - } /* while (ip < ilimit) */ /* Return the last literals size */ From 81fda0419ec9c8fef31cff28cd9091c796a34acb Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 4 Mar 2020 17:57:15 -0800 Subject: [PATCH 226/402] [opt] Only update repcodes upon arrival --- lib/compress/zstd_opt.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index fe44ebaf13e..14950622079 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -894,7 +894,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, for (matchNb = 0; matchNb < nbMatches; matchNb++) { U32 const offset = matches[matchNb].off; U32 const end = matches[matchNb].len; - repcodes_t const repHistory = ZSTD_updateRep(rep, offset, ll0); for ( ; pos <= end ; pos++ ) { U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel); U32 const sequencePrice = literalsPrice + matchPrice; @@ -904,8 +903,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, opt[pos].off = offset; opt[pos].litlen = litlen; opt[pos].price = sequencePrice; - ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory)); - memcpy(opt[pos].rep, &repHistory, sizeof(repHistory)); } } last_pos = pos-1; } @@ -932,7 +929,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, opt[cur].off = 0; opt[cur].litlen = litlen; opt[cur].price = price; - memcpy(opt[cur].rep, opt[cur-1].rep, sizeof(opt[cur].rep)); } else { DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)", inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), @@ -940,6 +936,21 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } } + /* Set the repcodes of the current position. We must do it here + * because we rely on the repcodes of the 2nd to last sequence being + * correct to set the next chunks repcodes during the backward + * traversal. + */ + ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t)); + assert(cur >= opt[cur].mlen); + if (opt[cur].mlen != 0) { + U32 const prev = cur - opt[cur].mlen; + repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0); + memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); + } else { + memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); + } + /* last match must start at a minimum distance of 8 from oend */ if (inr > ilimit) continue; @@ -980,7 +991,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* set prices using matches found at position == cur */ for (matchNb = 0; matchNb < nbMatches; matchNb++) { U32 const offset = matches[matchNb].off; - repcodes_t const repHistory = ZSTD_updateRep(opt[cur].rep, offset, ll0); U32 const lastML = matches[matchNb].len; U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch; U32 mlen; @@ -1000,8 +1010,6 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, opt[pos].off = offset; opt[pos].litlen = litlen; opt[pos].price = price; - ZSTD_STATIC_ASSERT(sizeof(opt[pos].rep) == sizeof(repHistory)); - memcpy(opt[pos].rep, &repHistory, sizeof(repHistory)); } else { DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)", pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price)); From 4c72a1a9c2dd2a1e5268289c21a8df07428eda0d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 5 Mar 2020 09:55:38 -0800 Subject: [PATCH 227/402] adding vector to main loop --- lib/compress/zstd_fast.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 6dbefee6b7f..8d4c82b1f00 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -80,6 +80,10 @@ ZSTD_compressBlock_fast_generic( } /* Main Search Loop */ +#ifdef __INTEL_COMPILER + #pragma vector always + #pragma ivdep +#endif while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */ size_t mLength; BYTE const* ip2 = ip0 + 2; From 85d0efd619a03a25d7ae1c95400f2580c7e5b7f3 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 5 Mar 2020 10:02:48 -0800 Subject: [PATCH 228/402] Removing no-tree-vectorize for intel --- lib/common/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 228845aa923..4213dfcf361 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -136,7 +136,7 @@ /* vectorization * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ -#if !defined(__clang__) && defined(__GNUC__) +#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) # else From a75e5f2ffc46ac771e41a273cc2a9d932a52fc67 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 5 Mar 2020 11:52:15 -0800 Subject: [PATCH 229/402] bitscan add undef check --- lib/common/bitstream.h | 3 +-- lib/common/zstd_internal.h | 3 +-- lib/compress/zstd_compress_internal.h | 12 ++++-------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index fe3148eebd0..c84c0ed9133 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -162,8 +162,7 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val) { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; - _BitScanReverse ( &r, val ); - return (unsigned) r; + _BitScanReverse ( &r, val ) ? (unsigned)r : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index d0b014358e5..1b023131444 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -298,8 +298,7 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; - _BitScanReverse(&r, val); - return (unsigned)r; + _BitScanReverse(&r, val) ? (unsigned)r : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 243f0e075ee..8fd08dad3de 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -448,8 +448,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) unsigned long r = 0; - _BitScanForward64( &r, (U64)val ); - return (unsigned)(r>>3); + return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_ctzll((U64)val) >> 3); # else @@ -466,8 +465,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* 32 bits */ # if defined(_MSC_VER) unsigned long r=0; - _BitScanForward( &r, (U32)val ); - return (unsigned)(r>>3); + _BitScanForward( &r, (U32)val ) ? return (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) return (__builtin_ctz((U32)val) >> 3); # else @@ -482,8 +480,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) unsigned long r = 0; - _BitScanReverse64( &r, val ); - return (unsigned)(r>>3); + _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_clzll(val) >> 3); # else @@ -497,8 +494,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* 32 bits */ # if defined(_MSC_VER) unsigned long r = 0; - _BitScanReverse( &r, (unsigned long)val ); - return (unsigned)(r>>3); + _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) return (__builtin_clz((U32)val) >> 3); # else From dba3abc95a9a3466f66970b0557a6430e82185bc Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 5 Mar 2020 12:20:59 -0800 Subject: [PATCH 230/402] Missed returns --- lib/common/bitstream.h | 2 +- lib/common/zstd_internal.h | 2 +- lib/compress/zstd_compress_internal.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index c84c0ed9133..ff891ca8f39 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -162,7 +162,7 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val) { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; - _BitScanReverse ( &r, val ) ? (unsigned)r : 0; + return _BitScanReverse ( &r, val ) ? (unsigned)r : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 1b023131444..04d2ac80d8a 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -298,7 +298,7 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus { # if defined(_MSC_VER) /* Visual */ unsigned long r=0; - _BitScanReverse(&r, val) ? (unsigned)r : 0; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 8fd08dad3de..a004d0a3c6d 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -465,7 +465,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* 32 bits */ # if defined(_MSC_VER) unsigned long r=0; - _BitScanForward( &r, (U32)val ) ? return (unsigned)(r >> 3) : 0; + return _BitScanForward( &r, (U32)val ) ? return (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) return (__builtin_ctz((U32)val) >> 3); # else @@ -480,7 +480,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) unsigned long r = 0; - _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; + return _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_clzll(val) >> 3); # else @@ -494,7 +494,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* 32 bits */ # if defined(_MSC_VER) unsigned long r = 0; - _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0; + return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) return (__builtin_clz((U32)val) >> 3); # else From 167244a64fbd1c7d8623bdcacec31bbbe4d6ebdb Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 13:07:29 -0500 Subject: [PATCH 231/402] --no-content-size cli --- programs/fileio.c | 8 +++++++- programs/fileio.h | 1 + programs/zstdcli.c | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index e08c7f3501f..288a73d327c 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -323,6 +323,7 @@ struct FIO_prefs_s { int excludeCompressedFiles; int patchFromMode; + int noContentSize; }; @@ -494,6 +495,11 @@ void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value) prefs->patchFromMode = value != 0; } +void FIO_setNoContentSize(FIO_prefs_t* const prefs, int value) +{ + prefs->noContentSize = value != 0; +} + /*-************************************* * Functions ***************************************/ @@ -1336,7 +1342,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, clock_t const cpuStart = clock(); U64 readsize = 0; U64 compressedfilesize = 0; - U64 const fileSize = UTIL_getFileSize(srcFileName); + U64 const fileSize = !prefs->noContentSize ? UTIL_getFileSize(srcFileName) : UTIL_FILESIZE_UNKNOWN; DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize); /* compression format selection */ diff --git a/programs/fileio.h b/programs/fileio.h index c592542e55a..ec2f28dc5f7 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -95,6 +95,7 @@ void FIO_setNoProgress(unsigned noProgress); void FIO_setNotificationLevel(int level); void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles); void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value); +void FIO_setNoContentSize(FIO_prefs_t* const prefs, int value); /*-************************************* * Single File functions diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b7f068ac1c9..557c95dfd07 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -634,7 +634,8 @@ int main(int const argCount, const char* argv[]) setRealTimePrio = 0, singleThread = 0, showDefaultCParams = 0, - ultra=0; + ultra=0, + noContentSize=0; double compressibility = 0.5; unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */ size_t blockSize = 0; @@ -748,6 +749,7 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; } if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; } + if (!strcmp(argument, "--no-content-size")) { noContentSize = 1; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } @@ -1256,6 +1258,7 @@ int main(int const argCount, const char* argv[]) FIO_setMemLimit(prefs, memLimit); if (operation==zom_compress) { #ifndef ZSTD_NOCOMPRESS + FIO_setNoContentSize(prefs, noContentSize); FIO_setNbWorkers(prefs, nbWorkers); FIO_setBlockSize(prefs, (int)blockSize); if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, (int)g_overlapLog); From 03ee18d9c55849c585d2a5582565ab635b93d40d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 14:00:52 -0500 Subject: [PATCH 232/402] Adding (void)noContentSize --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 557c95dfd07..319c661258c 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1306,7 +1306,7 @@ int main(int const argCount, const char* argv[]) else operationResult = FIO_compressMultipleFilenames(prefs, filenames->fileNames, (unsigned)filenames->tableSize, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams); #else - (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; /* not used when ZSTD_NOCOMPRESS set */ + (void)noContentSize; (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; /* not used when ZSTD_NOCOMPRESS set */ DISPLAY("Compression not supported \n"); #endif } else { /* decompression or test */ From 6d8e761ba3e696e62302b913d5a004b070a700d3 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 14:12:52 -0500 Subject: [PATCH 233/402] Inverting content size prefs bool --- programs/fileio.c | 8 ++++---- programs/fileio.h | 2 +- programs/zstdcli.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 288a73d327c..1a0bb97c0c0 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -323,7 +323,7 @@ struct FIO_prefs_s { int excludeCompressedFiles; int patchFromMode; - int noContentSize; + int contentSize; }; @@ -495,9 +495,9 @@ void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value) prefs->patchFromMode = value != 0; } -void FIO_setNoContentSize(FIO_prefs_t* const prefs, int value) +void FIO_setContentSize(FIO_prefs_t* const prefs, int value) { - prefs->noContentSize = value != 0; + prefs->contentSize = value != 0; } /*-************************************* @@ -1342,7 +1342,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, clock_t const cpuStart = clock(); U64 readsize = 0; U64 compressedfilesize = 0; - U64 const fileSize = !prefs->noContentSize ? UTIL_getFileSize(srcFileName) : UTIL_FILESIZE_UNKNOWN; + U64 const fileSize = prefs->contentSize ? UTIL_getFileSize(srcFileName) : UTIL_FILESIZE_UNKNOWN; DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize); /* compression format selection */ diff --git a/programs/fileio.h b/programs/fileio.h index ec2f28dc5f7..64a7035b183 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -95,7 +95,7 @@ void FIO_setNoProgress(unsigned noProgress); void FIO_setNotificationLevel(int level); void FIO_setExcludeCompressedFile(FIO_prefs_t* const prefs, int excludeCompressedFiles); void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value); -void FIO_setNoContentSize(FIO_prefs_t* const prefs, int value); +void FIO_setContentSize(FIO_prefs_t* const prefs, int value); /*-************************************* * Single File functions diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 319c661258c..ebdfca75c85 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -635,7 +635,7 @@ int main(int const argCount, const char* argv[]) singleThread = 0, showDefaultCParams = 0, ultra=0, - noContentSize=0; + contentSize=1; double compressibility = 0.5; unsigned bench_nbSeconds = 3; /* would be better if this value was synchronized from bench */ size_t blockSize = 0; @@ -749,7 +749,7 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; } if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; } - if (!strcmp(argument, "--no-content-size")) { noContentSize = 1; continue; } + if (!strcmp(argument, "--no-content-size")) { contentSize = 0; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; } if (!strcmp(argument, "--single-thread")) { nbWorkers = 0; singleThread = 1; continue; } @@ -1258,7 +1258,7 @@ int main(int const argCount, const char* argv[]) FIO_setMemLimit(prefs, memLimit); if (operation==zom_compress) { #ifndef ZSTD_NOCOMPRESS - FIO_setNoContentSize(prefs, noContentSize); + FIO_setContentSize(prefs, contentSize); FIO_setNbWorkers(prefs, nbWorkers); FIO_setBlockSize(prefs, (int)blockSize); if (g_overlapLog!=OVERLAP_LOG_DEFAULT) FIO_setOverlapLog(prefs, (int)g_overlapLog); @@ -1306,7 +1306,7 @@ int main(int const argCount, const char* argv[]) else operationResult = FIO_compressMultipleFilenames(prefs, filenames->fileNames, (unsigned)filenames->tableSize, outDirName, outFileName, suffix, dictFileName, cLevel, compressionParams); #else - (void)noContentSize; (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; /* not used when ZSTD_NOCOMPRESS set */ + (void)contentSize; (void)suffix; (void)adapt; (void)rsyncable; (void)ultra; (void)cLevel; (void)ldmFlag; (void)literalCompressionMode; (void)targetCBlockSize; (void)streamSrcSize; (void)srcSizeHint; (void)ZSTD_strategyMap; /* not used when ZSTD_NOCOMPRESS set */ DISPLAY("Compression not supported \n"); #endif } else { /* decompression or test */ From 43874730f42f5647cb9b1bb5870329caee35ba4e Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 14:19:05 -0500 Subject: [PATCH 234/402] Adding --content-size --- programs/zstdcli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index ebdfca75c85..8e86c282b17 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -749,6 +749,7 @@ int main(int const argCount, const char* argv[]) if (!strcmp(argument, "--priority=rt")) { setRealTimePrio = 1; continue; } if (!strcmp(argument, "--output-dir-flat")) {nextArgumentIsOutDirName=1; lastCommand=1; continue; } if (!strcmp(argument, "--show-default-cparams")) { showDefaultCParams = 1; continue; } + if (!strcmp(argument, "--content-size")) { contentSize = 1; continue; } if (!strcmp(argument, "--no-content-size")) { contentSize = 0; continue; } if (!strcmp(argument, "--adapt")) { adapt = 1; continue; } if (longCommandWArg(&argument, "--adapt=")) { adapt = 1; if (!parseAdaptParameters(argument, &adaptMin, &adaptMax)) { badusage(programName); CLEAN_RETURN(1); } continue; } From fae64b3390899599293af97bb583d27abfa759f5 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 14:44:38 -0500 Subject: [PATCH 235/402] Adding test for --[no-]content-size --- tests/playTests.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/playTests.sh b/tests/playTests.sh index c7605cc480f..c020127fe59 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -469,6 +469,19 @@ ls tmp* > tmpList $ZSTD -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3 # can trigger an overflow of internal file list rm -rf tmp* +println "\n===> --[no-]content-size tests" + +$DATAGEN > tmp_contentsize +$ZSTD -f tmp_contentsize +$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" +$ZSTD -f --no-content-size tmp_contentsize +$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" && die +$ZSTD -f --content-size tmp_contentsize +$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" +$ZSTD -f --content-size --no-content-size tmp_contentsize +$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" && die +rm -rf tmp* + println "test : show-default-cparams regular" $DATAGEN > tmp $ZSTD --show-default-cparams -f tmp From 84d6bd4c7fc466cfd45b8dce22c5af6e6cd10c52 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 14:49:04 -0500 Subject: [PATCH 236/402] Adding documentation --- programs/zstd.1.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index dc6e9b5d2d4..5b557e65c6d 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -198,6 +198,10 @@ the last one takes effect. default: enabled when output is into a file, and disabled when output is stdout. This setting overrides default and can force sparse mode over stdout. +* `--[no-]content-size`: + enable / disable whether or not the original size of the file is placed in + the header of the compressed file. The default option is + --content-size (meaning that the original size will be placed in the header). * `--rm`: remove source file(s) after successful compression or decompression * `-k`, `--keep`: From 9388dac2c0fee6a88b4e7d0d6bd10ad883aef47a Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 9 Mar 2020 15:40:18 -0500 Subject: [PATCH 237/402] Setting ZSTD_c_contentSizeFlag instead of UNKNOWN filesize --- programs/fileio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index 1a0bb97c0c0..c833336dc8a 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -823,6 +823,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) ); CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, prefs->contentSize) ); /* compression level */ CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) ); /* max compressed block size */ @@ -1342,7 +1343,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, clock_t const cpuStart = clock(); U64 readsize = 0; U64 compressedfilesize = 0; - U64 const fileSize = prefs->contentSize ? UTIL_getFileSize(srcFileName) : UTIL_FILESIZE_UNKNOWN; + U64 const fileSize = UTIL_getFileSize(srcFileName); DISPLAYLEVEL(5, "%s: %u bytes \n", srcFileName, (unsigned)fileSize); /* compression format selection */ From 43fc88f44358d659c2d07c58710d131d370545e6 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 10 Mar 2020 14:57:27 -0500 Subject: [PATCH 238/402] Adding comment and remvoing ivdep --- lib/compress/zstd_fast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 8d4c82b1f00..09e220b3abc 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -81,8 +81,11 @@ ZSTD_compressBlock_fast_generic( /* Main Search Loop */ #ifdef __INTEL_COMPILER + /* From intel 'The vector pragma indicates that the loop should be + * vectorized if it is legal to do so'. Can be used together with + * #pragma ivdep (but have opted to exclude that because intel + * warns against using it).*/ #pragma vector always - #pragma ivdep #endif while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */ size_t mLength; From a89c45bdbdee0e1f7a078dea91b5ef2e86fd76a4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 10 Mar 2020 15:19:48 -0500 Subject: [PATCH 239/402] Typo --- lib/compress/zstd_compress_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index a004d0a3c6d..0d54652fa30 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -465,7 +465,7 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* 32 bits */ # if defined(_MSC_VER) unsigned long r=0; - return _BitScanForward( &r, (U32)val ) ? return (unsigned)(r >> 3) : 0; + return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0; # elif defined(__GNUC__) && (__GNUC__ >= 3) return (__builtin_ctz((U32)val) >> 3); # else From dbdeca1412ca370acbb9480641e02137c7d94e4a Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 13 Mar 2020 09:39:33 -0500 Subject: [PATCH 240/402] Edit distance match finder --- contrib/match_finders/README.md | 42 +++ contrib/match_finders/zstd_edist.c | 558 +++++++++++++++++++++++++++++ contrib/match_finders/zstd_edist.h | 70 ++++ 3 files changed, 670 insertions(+) create mode 100644 contrib/match_finders/README.md create mode 100644 contrib/match_finders/zstd_edist.c create mode 100644 contrib/match_finders/zstd_edist.h diff --git a/contrib/match_finders/README.md b/contrib/match_finders/README.md new file mode 100644 index 00000000000..0f4a3b1ce82 --- /dev/null +++ b/contrib/match_finders/README.md @@ -0,0 +1,42 @@ +## Edit Distance Match Finder + +``` +/* This match finder leverages techniques used in file comparison algorithms + * to find matches between a dictionary and a source file. + * + * The original motivation for studying this approach was to try and optimize + * Zstandard for the use case of patching: the most common scenario being + * updating an existing software package with the next version. When patching, + * the difference between the old version of the package and the new version + * is generally tiny (most of the new file will be identical to + * the old one). In more technical terms, the edit distance (the minimal number + * of changes required to take one sequence of bytes to another) between the + * files would be small relative to the size of the file. + * + * Various 'diffing' algorithms utilize this notion of edit distance and + * the corrensponding concept of a minimal edit script between two + * sequences to identify the regions within two files where they differ. + * The core algorithm used in this match finder is described in: + * + * "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + * Algorithmica Vol. 1, 1986, pp. 251-266, + * . + * + * Additional algorithmic heuristics for speed improvement have also been included. + * These we inspired from implementations of various regular and binary diffing + * algorithms such as GNU diff, bsdiff, and Xdelta. + * + * Note: after some experimentation, this approach proved to not provide enough + * utility to justify the additional CPU used in finding matches. The one area + * where this approach consistenly outperforms Zstandard even on level 19 is + * when compressing small files (<10 KB) using a equally small dictionary that + * is very similar to the source file. For the use case that this was intended, + * (large similar files) this approach by itself took 5-10X longer than zstd-19 and + * generally resulted in 2-3X larger files. The core advantage that zstd-19 has + * over this appraoch for match finding is the overlapping matches. This approach + * cannot find any. + * + * I'm leaving this in the contrib section in case this ever becomes interesting + * to explore again. + * */ +``` diff --git a/contrib/match_finders/zstd_edist.c b/contrib/match_finders/zstd_edist.c new file mode 100644 index 00000000000..aab545fd3ba --- /dev/null +++ b/contrib/match_finders/zstd_edist.c @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/*-************************************* +* Dependencies +***************************************/ + +/* Currently relies on qsort when combining contiguous matches. This can probabily + * be avoided but would require changes to the algorithm. The qsort is far from + * the bottleneck in this algorithm even for medium sized files so it's probably + * not worth trying to address */ +#include +#include + +#include "zstd_edist.h" +#include "mem.h" + +/*-************************************* +* Constants +***************************************/ + +/* Just a sential for the entires of the diagnomal matrix */ +#define ZSTD_EDIST_DIAG_MAX (S32)(1 << 30) + +/* How large should a snake be to be considered a 'big' snake. + * For an explanation of what a 'snake' is with respect to the + * edit distance matrix, see the linked paper in zstd_edist.h */ +#define ZSTD_EDIST_SNAKE_THRESH 20 + +/* After how many iterations should we start to use the heuristic + * based on 'big' snakes */ +#define ZSTD_EDIST_SNAKE_ITER_THRESH 200 + +/* After how many iterations should be just give up and take + * the best availabe edit script for this round */ +#define ZSTD_EDIST_EXPENSIVE_THRESH 1024 + +/*-************************************* +* Structures +***************************************/ + +typedef struct { + U32 dictIdx; + U32 srcIdx; + U32 matchLength; +} ZSTD_eDist_match; + +typedef struct { + const BYTE* dict; + const BYTE* src; + size_t dictSize; + size_t srcSize; + S32* forwardDiag; /* Entires of the forward diagonal stored here */ + S32* backwardDiag; /* Entires of the backward diagonal stored here. + * Note: this buffer and the 'forwardDiag' buffer + * are contiguous. See the ZSTD_eDist_genSequences */ + ZSTD_eDist_match* matches; /* Accumulate matches of length 1 in this buffer. + * In a subsequence post-processing step, we combine + * contiguous matches. */ + U32 nbMatches; +} ZSTD_eDist_state; + +typedef struct { + S32 dictMid; /* The mid diagonal for the dictionary */ + S32 srcMid; /* The mid diagonal for the source */ + int lowUseHeuristics; /* Should we use heuristics for the low part */ + int highUseHeuristics; /* Should we use heuristics for the high part */ +} ZSTD_eDist_partition; + +/*-************************************* +* Internal +***************************************/ + +static void ZSTD_eDist_diag(ZSTD_eDist_state* state, + ZSTD_eDist_partition* partition, + S32 dictLow, S32 dictHigh, S32 srcLow, + S32 srcHigh, int useHeuristics) +{ + S32* const forwardDiag = state->forwardDiag; + S32* const backwardDiag = state->backwardDiag; + const BYTE* const dict = state->dict; + const BYTE* const src = state->src; + + S32 const diagMin = dictLow - srcHigh; + S32 const diagMax = dictHigh - srcLow; + S32 const forwardMid = dictLow - srcLow; + S32 const backwardMid = dictHigh - srcHigh; + + S32 forwardMin = forwardMid; + S32 forwardMax = forwardMid; + S32 backwardMin = backwardMid; + S32 backwardMax = backwardMid; + int odd = (forwardMid - backwardMid) & 1; + U32 iterations; + + forwardDiag[forwardMid] = dictLow; + backwardDiag[backwardMid] = dictHigh; + + /* Main loop for updating diag entries. Unless useHeuristics is + * set to false, this loop will run until it finds the minimal + * edit script */ + for (iterations = 1;;iterations++) { + S32 diag; + int bigSnake = 0; + + if (forwardMin > diagMin) { + forwardMin--; + forwardDiag[forwardMin - 1] = -1; + } else { + forwardMin++; + } + + if (forwardMax < diagMax) { + forwardMax++; + forwardDiag[forwardMax + 1] = -1; + } else { + forwardMax--; + } + + for (diag = forwardMax; diag >= forwardMin; diag -= 2) { + S32 dictIdx; + S32 srcIdx; + S32 low = forwardDiag[diag - 1]; + S32 high = forwardDiag[diag + 1]; + S32 dictIdx0 = low < high ? high : low + 1; + + for (dictIdx = dictIdx0, srcIdx = dictIdx0 - diag; + dictIdx < dictHigh && srcIdx < srcHigh && dict[dictIdx] == src[srcIdx]; + dictIdx++, srcIdx++) continue; + + if (dictIdx - dictIdx0 > ZSTD_EDIST_SNAKE_THRESH) + bigSnake = 1; + + forwardDiag[diag] = dictIdx; + + if (odd && backwardMin <= diag && diag <= backwardMax && backwardDiag[diag] <= dictIdx) { + partition->dictMid = dictIdx; + partition->srcMid = srcIdx; + partition->lowUseHeuristics = 0; + partition->highUseHeuristics = 0; + return; + } + } + + if (backwardMin > diagMin) { + backwardMin--; + backwardDiag[backwardMin - 1] = ZSTD_EDIST_DIAG_MAX; + } else { + backwardMin++; + } + + if (backwardMax < diagMax) { + backwardMax++; + backwardDiag[backwardMax + 1] = ZSTD_EDIST_DIAG_MAX; + } else { + backwardMax--; + } + + + for (diag = backwardMax; diag >= backwardMin; diag -= 2) { + S32 dictIdx; + S32 srcIdx; + S32 low = backwardDiag[diag - 1]; + S32 high = backwardDiag[diag + 1]; + S32 dictIdx0 = low < high ? low : high - 1; + + for (dictIdx = dictIdx0, srcIdx = dictIdx0 - diag; + dictLow < dictIdx && srcLow < srcIdx && dict[dictIdx - 1] == src[srcIdx - 1]; + dictIdx--, srcIdx--) continue; + + if (dictIdx0 - dictIdx > ZSTD_EDIST_SNAKE_THRESH) + bigSnake = 1; + + backwardDiag[diag] = dictIdx; + + if (!odd && forwardMin <= diag && diag <= forwardMax && dictIdx <= forwardDiag[diag]) { + partition->dictMid = dictIdx; + partition->srcMid = srcIdx; + partition->lowUseHeuristics = 0; + partition->highUseHeuristics = 0; + return; + } + } + + if (!useHeuristics) + continue; + + /* Everything under this point is a heuritic. Using these will + * substantially speed up the match finding. In some cases, taking + * the total match finding time from several minutes to seconds. + * Of course, the caveat is that the edit script found may no longer + * be optimal */ + + /* Big snake heuristic */ + if (iterations > ZSTD_EDIST_SNAKE_ITER_THRESH && bigSnake) { + { + S32 best = 0; + + for (diag = forwardMax; diag >= forwardMin; diag -= 2) { + S32 diagDiag = diag - forwardMid; + S32 dictIdx = forwardDiag[diag]; + S32 srcIdx = dictIdx - diag; + S32 v = (dictIdx - dictLow) * 2 - diagDiag; + + if (v > 12 * (iterations + (diagDiag < 0 ? -diagDiag : diagDiag))) { + if (v > best + && dictLow + ZSTD_EDIST_SNAKE_THRESH <= dictIdx && dictIdx <= dictHigh + && srcLow + ZSTD_EDIST_SNAKE_THRESH <= srcIdx && srcIdx <= srcHigh) { + S32 k; + for (k = 1; dict[dictIdx - k] == src[srcIdx - k]; k++) { + if (k == ZSTD_EDIST_SNAKE_THRESH) { + best = v; + partition->dictMid = dictIdx; + partition->srcMid = srcIdx; + break; + } + } + } + } + } + + if (best > 0) { + partition->lowUseHeuristics = 0; + partition->highUseHeuristics = 1; + return; + } + } + + { + S32 best = 0; + + for (diag = backwardMax; diag >= backwardMin; diag -= 2) { + S32 diagDiag = diag - backwardMid; + S32 dictIdx = backwardDiag[diag]; + S32 srcIdx = dictIdx - diag; + S32 v = (dictHigh - dictIdx) * 2 + diagDiag; + + if (v > 12 * (iterations + (diagDiag < 0 ? -diagDiag : diagDiag))) { + if (v > best + && dictLow < dictIdx && dictIdx <= dictHigh - ZSTD_EDIST_SNAKE_THRESH + && srcLow < srcIdx && srcIdx <= srcHigh - ZSTD_EDIST_SNAKE_THRESH) { + int k; + for (k = 0; dict[dictIdx + k] == src[srcIdx + k]; k++) { + if (k == ZSTD_EDIST_SNAKE_THRESH - 1) { + best = v; + partition->dictMid = dictIdx; + partition->srcMid = srcIdx; + break; + } + } + } + } + } + + if (best > 0) { + partition->lowUseHeuristics = 1; + partition->highUseHeuristics = 0; + return; + } + } + } + + /* More general 'too expensive' heuristic */ + if (iterations >= ZSTD_EDIST_EXPENSIVE_THRESH) { + S32 forwardDictSrcBest; + S32 forwardDictBest = 0; + S32 backwardDictSrcBest; + S32 backwardDictBest = 0; + + forwardDictSrcBest = -1; + for (diag = forwardMax; diag >= forwardMin; diag -= 2) { + S32 dictIdx = MIN(forwardDiag[diag], dictHigh); + S32 srcIdx = dictIdx - diag; + + if (srcHigh < srcIdx) { + dictIdx = srcHigh + diag; + srcIdx = srcHigh; + } + + if (forwardDictSrcBest < dictIdx + srcIdx) { + forwardDictSrcBest = dictIdx + srcIdx; + forwardDictBest = dictIdx; + } + } + + backwardDictSrcBest = ZSTD_EDIST_DIAG_MAX; + for (diag = backwardMax; diag >= backwardMin; diag -= 2) { + S32 dictIdx = MAX(dictLow, backwardDiag[diag]); + S32 srcIdx = dictIdx - diag; + + if (srcIdx < srcLow) { + dictIdx = srcLow + diag; + srcIdx = srcLow; + } + + if (dictIdx + srcIdx < backwardDictSrcBest) { + backwardDictSrcBest = dictIdx + srcIdx; + backwardDictBest = dictIdx; + } + } + + if ((dictHigh + srcHigh) - backwardDictSrcBest < forwardDictSrcBest - (dictLow + srcLow)) { + partition->dictMid = forwardDictBest; + partition->srcMid = forwardDictSrcBest - forwardDictBest; + partition->lowUseHeuristics = 0; + partition->highUseHeuristics = 1; + } else { + partition->dictMid = backwardDictBest; + partition->srcMid = backwardDictSrcBest - backwardDictBest; + partition->lowUseHeuristics = 1; + partition->highUseHeuristics = 0; + } + return; + } + } +} + +static void ZSTD_eDist_insertMatch(ZSTD_eDist_state* state, + S32 const dictIdx, S32 const srcIdx) +{ + state->matches[state->nbMatches].dictIdx = dictIdx; + state->matches[state->nbMatches].srcIdx = srcIdx; + state->matches[state->nbMatches].matchLength = 1; + state->nbMatches++; +} + +static int ZSTD_eDist_compare(ZSTD_eDist_state* state, + S32 dictLow, S32 dictHigh, S32 srcLow, + S32 srcHigh, int useHeuristics) +{ + const BYTE* const dict = state->dict; + const BYTE* const src = state->src; + + /* Found matches while traversing from the low end */ + while (dictLow < dictHigh && srcLow < srcHigh && dict[dictLow] == src[srcLow]) { + ZSTD_eDist_insertMatch(state, dictLow, srcLow); + dictLow++; + srcLow++; + } + + /* Found matches while traversing from the high end */ + while (dictLow < dictHigh && srcLow < srcHigh && dict[dictHigh - 1] == src[srcHigh - 1]) { + ZSTD_eDist_insertMatch(state, dictHigh - 1, srcHigh - 1); + dictHigh--; + srcHigh--; + } + + /* If the low and high end end up touching. If we wanted to make + * note of the differences like most diffing algorithms do, we would + * do so here. In our case, we're only concerned with matches + * Note: if you wanted to find the edit distance of the algorithm, + * you could just accumulate the cost for an insertion/deletion + * below. */ + if (dictLow == dictHigh) { + while (srcLow < srcHigh) { + /* Reaching this point means inserting src[srcLow] into + * the current position of dict */ + srcLow++; + } + } else if (srcLow == srcHigh) { + while (dictLow < dictHigh) { + /* Reaching this point means deleteing dict[dictLow] from + * the current positino of dict */ + dictLow++; + } + } else { + ZSTD_eDist_partition partition; + partition.dictMid = 0; + partition.srcMid = 0; + ZSTD_eDist_diag(state, &partition, dictLow, dictHigh, + srcLow, srcHigh, useHeuristics); + if (ZSTD_eDist_compare(state, dictLow, partition.dictMid, + srcLow, partition.srcMid, partition.lowUseHeuristics)) + return 1; + if (ZSTD_eDist_compare(state, partition.dictMid, dictHigh, + partition.srcMid, srcHigh, partition.highUseHeuristics)) + return 1; + } + + return 0; +} + +static int ZSTD_eDist_matchComp(const void* p, const void* q) +{ + S32 const l = ((ZSTD_eDist_match*)p)->srcIdx; + S32 const r = ((ZSTD_eDist_match*)q)->srcIdx; + return (l - r); +} + +/* The matches from the approach above will all be of the form + * (dictIdx, srcIdx, 1). this method combines contiguous matches + * of length MINMATCH or greater. Matches less than MINMATCH + * are discarded */ +static void ZSTD_eDist_combineMatches(ZSTD_eDist_state* state) +{ + /* Create a new buffer to put the combined matches into + * and memcpy to state->matches after */ + ZSTD_eDist_match* combinedMatches = + ZSTD_malloc(state->nbMatches * sizeof(ZSTD_eDist_match), + ZSTD_defaultCMem); + + U32 nbCombinedMatches = 1; + size_t i; + + /* Make sure that the srcIdx and dictIdx are in sorted order. + * The combination step won't work otherwise */ + qsort(state->matches, state->nbMatches, sizeof(ZSTD_eDist_match), ZSTD_eDist_matchComp); + + memcpy(combinedMatches, state->matches, sizeof(ZSTD_eDist_match)); + for (i = 1; i < state->nbMatches; i++) { + ZSTD_eDist_match const match = state->matches[i]; + ZSTD_eDist_match const combinedMatch = + combinedMatches[nbCombinedMatches - 1]; + if (combinedMatch.srcIdx + combinedMatch.matchLength == match.srcIdx && + combinedMatch.dictIdx + combinedMatch.matchLength == match.dictIdx) { + combinedMatches[nbCombinedMatches - 1].matchLength++; + } else { + /* Discard matches that are less than MINMATCH */ + if (combinedMatches[nbCombinedMatches - 1].matchLength < MINMATCH) { + nbCombinedMatches--; + } + + memcpy(combinedMatches + nbCombinedMatches, + state->matches + i, sizeof(ZSTD_eDist_match)); + nbCombinedMatches++; + } + } + memcpy(state->matches, combinedMatches, nbCombinedMatches * sizeof(ZSTD_eDist_match)); + state->nbMatches = nbCombinedMatches; + ZSTD_free(combinedMatches, ZSTD_defaultCMem); +} + +static size_t ZSTD_eDist_convertMatchesToSequences(ZSTD_Sequence* sequences, + ZSTD_eDist_state* state) +{ + const ZSTD_eDist_match* matches = state->matches; + size_t const nbMatches = state->nbMatches; + size_t const dictSize = state->dictSize; + size_t nbSequences = 0; + size_t i; + for (i = 0; i < nbMatches; i++) { + ZSTD_eDist_match const match = matches[i]; + U32 const litLength = !i ? match.srcIdx : + match.srcIdx - (matches[i - 1].srcIdx + matches[i - 1].matchLength); + U32 const offset = (match.srcIdx + dictSize) - match.dictIdx; + U32 const matchLength = match.matchLength; + sequences[nbSequences].offset = offset; + sequences[nbSequences].litLength = litLength; + sequences[nbSequences].matchLength = matchLength; + nbSequences++; + } + return nbSequences; +} + +/*-************************************* +* Interal utils +***************************************/ + +static size_t ZSTD_eDist_hamingDist(const BYTE* const a, + const BYTE* const b, size_t n) +{ + size_t i; + size_t dist = 0; + for (i = 0; i < n; i++) + dist += a[i] != b[i]; + return dist; +} + +/* This is a pretty naive recursive implementation that should only + * be used for quick tests obviously. Don't try and run this on a + * GB file or something. There are faster implementations. Use those + * if you need to run it for large files. */ +static size_t ZSTD_eDist_levenshteinDist(const BYTE* const s, + size_t const sn, const BYTE* const t, + size_t const tn) +{ + size_t a, b, c; + + if (!sn) + return tn; + if (!tn) + return sn; + + if (s[sn - 1] == t[tn - 1]) + return ZSTD_eDist_levenshteinDist( + s, sn - 1, t, tn - 1); + + a = ZSTD_eDist_levenshteinDist(s, sn - 1, t, tn - 1); + b = ZSTD_eDist_levenshteinDist(s, sn, t, tn - 1); + c = ZSTD_eDist_levenshteinDist(s, sn - 1, t, tn); + + if (a > b) + a = b; + if (a > c) + a = c; + + return a + 1; +} + +static void ZSTD_eDist_validateMatches(ZSTD_eDist_match* matches, + size_t const nbMatches, const BYTE* const dict, + size_t const dictSize, const BYTE* const src, + size_t const srcSize) +{ + size_t i; + for (i = 0; i < nbMatches; i++) { + ZSTD_eDist_match match = matches[i]; + U32 const dictIdx = match.dictIdx; + U32 const srcIdx = match.srcIdx; + U32 const matchLength = match.matchLength; + + assert(dictIdx + matchLength < dictSize); + assert(srcIdx + matchLength < srcSize); + assert(!memcmp(dict + dictIdx, src + srcIdx, matchLength)); + } +} + +/*-************************************* +* API +***************************************/ + +size_t ZSTD_eDist_genSequences(ZSTD_Sequence* sequences, + const void* dict, size_t dictSize, + const void* src, size_t srcSize, + int useHeuristics) +{ + size_t const nbDiags = dictSize + srcSize + 3; + S32* buffer = ZSTD_malloc(nbDiags * 2 * sizeof(S32), ZSTD_defaultCMem); + ZSTD_eDist_state state; + size_t nbSequences = 0; + + state.dict = (const BYTE*)dict; + state.src = (const BYTE*)src; + state.dictSize = dictSize; + state.srcSize = srcSize; + state.forwardDiag = buffer; + state.backwardDiag = buffer + nbDiags; + state.forwardDiag += srcSize + 1; + state.backwardDiag += srcSize + 1; + state.matches = ZSTD_malloc(srcSize * sizeof(ZSTD_eDist_match), ZSTD_defaultCMem); + state.nbMatches = 0; + + ZSTD_eDist_compare(&state, 0, dictSize, 0, srcSize, 1); + ZSTD_eDist_combineMatches(&state); + nbSequences = ZSTD_eDist_convertMatchesToSequences(sequences, &state); + + ZSTD_free(buffer, ZSTD_defaultCMem); + ZSTD_free(state.matches, ZSTD_defaultCMem); + + return nbSequences; +} diff --git a/contrib/match_finders/zstd_edist.h b/contrib/match_finders/zstd_edist.h new file mode 100644 index 00000000000..c775a498503 --- /dev/null +++ b/contrib/match_finders/zstd_edist.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* This match finder leverages techniques used in file comparison algorithms + * to find matches between a dictionary and a source file. + * + * The original motivation for studying this approach was to try and optimize + * Zstandard for the use case of patching: the most common scenario being + * updating an existing software package with the next version. When patching, + * the difference between the old version of the package and the new version + * is generally tiny (most of the new file will be identical to + * the old one). In more technical terms, the edit distance (the minimal number + * of changes required to take one sequence of bytes to another) between the + * files would be small relative to the size of the file. + * + * Various 'diffing' algorithms utilize this notion of edit distance and + * the corrensponding concept of a minimal edit script between two + * sequences to identify the regions within two files where they differ. + * The core algorithm used in this match finder is described in: + * + * "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + * Algorithmica Vol. 1, 1986, pp. 251-266, + * . + * + * Additional algorithmic heuristics for speed improvement have also been included. + * These we inspired from implementations of various regular and binary diffing + * algorithms such as GNU diff, bsdiff, and Xdelta. + * + * Note: after some experimentation, this approach proved to not provide enough + * utility to justify the additional CPU used in finding matches. The one area + * where this approach consistenly outperforms Zstandard even on level 19 is + * when compressing small files (<10 KB) using a equally small dictionary that + * is very similar to the source file. For the use case that this was intended, + * (large similar files) this approach by itself took 5-10X longer than zstd-19 and + * generally resulted in 2-3X larger files. The core advantage that zstd-19 has + * over this appraoch for match finding is the overlapping matches. This approach + * cannot find any. + * + * I'm leaving this in the contrib section in case this ever becomes interesting + * to explore again. + * */ + +#ifndef ZSTD_EDIST_H +#define ZSTD_EDIST_H + +/*-************************************* +* Dependencies +***************************************/ + +#include +#include "zstd_internal.h" /* ZSTD_Sequence */ + +/*! ZSTD_eDist_genSequences() : + * Will populate the provided ZSTD_Sequence buffer with sequences + * based on the optimal or near-optimal (depending on 'useHeuristics') + * edit script between 'dict' and 'src.' + * @return : the number of sequences found */ +size_t ZSTD_eDist_genSequences(ZSTD_Sequence* sequences, + const void* dict, size_t dictSize, + const void* src, size_t srcSize, + int useHeuristics); + +#endif From 7201980650c454fb5d9b4bcedd786b73b1076712 Mon Sep 17 00:00:00 2001 From: caoyzh Date: Sat, 14 Mar 2020 15:25:09 +0800 Subject: [PATCH 241/402] Optimize by prefetching on aarch64 --- lib/common/compiler.h | 3 +++ lib/compress/zstd_double_fast.c | 3 +++ lib/compress/zstd_fast.c | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 4213dfcf361..5fd92f0402d 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -114,6 +114,9 @@ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) +# elif defined(__aarch64__) +# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) +# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 2e657f7c426..ef09a6968be 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -198,6 +198,9 @@ size_t ZSTD_compressBlock_doubleFast_generic( } } ip += ((ip-anchor) >> kSearchStrength) + 1; +#if defined(__aarch64__) + PREFETCH_L1(ip+256); +#endif continue; _search_next_long: diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 09e220b3abc..556dc5a9a98 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -102,6 +102,11 @@ ZSTD_compressBlock_fast_generic( const BYTE* match0 = base + matchIndex0; const BYTE* match1 = base + matchIndex1; U32 offcode; + +#if defined(__aarch64__) + PREFETCH_L1(ip0+256); +#endif + hashTable[h0] = current0; /* update hash table */ hashTable[h1] = current1; /* update hash table */ From 22e7123a9a44b6b099b09920af47c435d255358f Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 23 Mar 2020 06:25:08 -0700 Subject: [PATCH 242/402] targetLen -> targetLength --- programs/zstd.1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index 5b557e65c6d..bb8b706b733 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -460,17 +460,17 @@ The list of available _options_: The minimum _mml_ is 3 and the maximum is 7. -- `targetLen`=_tlen_, `tlen`=_tlen_: +- `targetLength`=_tlen_, `tlen`=_tlen_: The impact of this field vary depending on selected strategy. For ZSTD\_btopt, ZSTD\_btultra and ZSTD\_btultra2, it specifies the minimum match length that causes match finder to stop searching. - A larger `targetLen` usually improves compression ratio + A larger `targetLength` usually improves compression ratio but decreases compression speed. - +t For ZSTD\_fast, it triggers ultra-fast mode when > 0. The value represents the amount of data skipped between match sampling. - Impact is reversed : a larger `targetLen` increases compression speed + Impact is reversed : a larger `targetLength` increases compression speed but decreases compression ratio. For all other strategies, this field has no impact. From 12e421b3c09aee78361a62c61f359fd8a5d930d3 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Thu, 30 Jan 2020 10:31:00 -0500 Subject: [PATCH 243/402] Fix testing documentation typo --- TESTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TESTING.md b/TESTING.md index 42cd48e7019..7e5305178b9 100644 --- a/TESTING.md +++ b/TESTING.md @@ -19,7 +19,7 @@ Medium tests run on every commit and pull request to `dev` branch, on TravisCI. They consist of the following tests: - The following tests run with UBsan and Asan on x86_64 and x86, as well as with Msan on x86_64 - - `tests/playTests.sh --test-long-data` + - `tests/playTests.sh --test-large-data` - Fuzzer tests: `tests/fuzzer.c`, `tests/zstreamtest.c`, and `tests/decodecorpus.c` - `tests/zstreamtest.c` under Tsan (streaming mode, including multithreaded mode) - Valgrind Test (`make -C tests valgrindTest`) (testing CLI and fuzzer under valgrind) From 3cbc3d37e74c23354b4f10ab3fcf663ed43082cf Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Mon, 23 Mar 2020 17:46:56 -0400 Subject: [PATCH 244/402] Add documentation for -T option --- tests/fuzzer.c | 3 ++- tests/zstreamtest.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 3c4aac7a8fc..1b47a19e2c0 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2833,7 +2833,8 @@ static int FUZ_usage(const char* programName) DISPLAY( " %s [args]\n", programName); DISPLAY( "\n"); DISPLAY( "Arguments :\n"); - DISPLAY( " -i# : Nb of tests (default:%i) \n", nbTestsDefault); + DISPLAY( " -i# : Number of tests (default:%i)\n", nbTestsDefault); + DISPLAY( " -T# : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\n"); DISPLAY( " -s# : Select seed (default:prompt user)\n"); DISPLAY( " -t# : Select starting test number (default:0)\n"); DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_compressibility_default); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 890e66f9ecb..26a1d1a4734 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -2373,7 +2373,8 @@ static int FUZ_usage(const char* programName) DISPLAY( " %s [args]\n", programName); DISPLAY( "\n"); DISPLAY( "Arguments :\n"); - DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault); + DISPLAY( " -i# : Number of tests (default:%u)\n", nbTestsDefault); + DISPLAY( " -T# : Max duration to run for. Overrides number of tests. (e.g. -T1m or -T60s for one minute)\n"); DISPLAY( " -s# : Select seed (default:prompt user)\n"); DISPLAY( " -t# : Select starting test number (default:0)\n"); DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT); From 496d8c8b77fbfafd0ccf56a5d4a502e412070627 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Mon, 23 Mar 2020 17:44:27 -0400 Subject: [PATCH 245/402] Respect the conventional BUILD_TESTS CMake option on the first configure --- build/cmake/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index be5ce15186f..70e8c0609ec 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -103,7 +103,14 @@ endif () option(ZSTD_BUILD_PROGRAMS "BUILD PROGRAMS" ON) option(ZSTD_BUILD_CONTRIB "BUILD CONTRIB" OFF) -option(ZSTD_BUILD_TESTS "BUILD TESTS" OFF) + +# Respect the conventional CMake option for enabling tests if it was specified on the first configure +if (BUILD_TESTING) + set(ZSTD_BUILD_TESTS_default ON) +else() + set(ZSTD_BUILD_TESTS_default OFF) +endif() +option(ZSTD_BUILD_TESTS "BUILD TESTS" ${ZSTD_BUILD_TESTS_default}) if (MSVC) option(ZSTD_USE_STATIC_RUNTIME "LINK TO STATIC RUN-TIME LIBRARIES" OFF) endif () From 8d0ee37ac0574908a1b8169180ca671c88b66903 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 18 Mar 2020 19:42:07 -0700 Subject: [PATCH 246/402] Align decompress sequences loop to 32+16 bytes The alignment is added before the loop, so this shouldn't hurt performance in any case. The only way it hurts is if there is already performance instability, and we force it to be stable but in the bad case. This consistently gets us into the good case with gcc-{7,8,9} on an Intel i9-9900K and clang-9. gcc-5 is 5% worse than its best case but has stable performance. We get consistently good behavior on my Macbook Pro compiled with both clang and gcc-8. It ends up in the 50% from DSB and 50% from MITE case, but the performance is the same as the 85% DSB case, so thats fine. --- lib/decompress/zstd_decompress_block.c | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index d4d23357186..9d60fdf30dd 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -974,6 +974,47 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, BIT_DStream_endOfBuffer < BIT_DStream_completed && BIT_DStream_completed < BIT_DStream_overflow); +#if defined(__GNUC__) && defined(__x86_64__) + /* Align the decompression loop to 32 + 16 bytes. + * + * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression + * speed swings based on the alignment of the decompression loop. This + * performance swing is caused by parts of the decompression loop falling + * out of the DSB. The entire decompression loop should fit in the DSB, + * when it can't we get much worse performance. You can measure if you've + * hit the good case or the bad case with this perf command for some + * compressed file test.zst: + * + * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \ + * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst + * + * If you see most cycles served out of the MITE you've hit the bad case. + * If you see most cycles served out of the DSB you've hit the good case. + * If it is pretty even then you may be in an okay case. + * + * I've been able to reproduce this issue on the following CPUs: + * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9 + * Use Instruments->Counters to get DSB/MITE cycles. + * I never got performance swings, but I was able to + * go from the good case of mostly DSB to half of the + * cycles served from MITE. + * - Coffeelake: Intel i9-9900k + * + * I haven't been able to reproduce the instability or DSB misses on any + * of the following CPUS: + * - Haswell + * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH + * - Skylake + * + * If you are seeing performance stability this script can help test. + * It tests on 4 commits in zstd where I saw performance change. + * + * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4 + */ + __asm__(".p2align 5"); + __asm__("nop"); + __asm__(".p2align 4"); +#endif for ( ; ; ) { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); From ac58c8d720869a4ffc1aa1413ace53af513bf3b4 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 26 Mar 2020 15:19:05 -0700 Subject: [PATCH 247/402] Fix copyright and license lines * All copyright lines now have -2020 instead of -present * All copyright lines include "Facebook, Inc" * All licenses are now standardized The copyright in `threading.{h,c}` is not changed because it comes from zstdmt. The copyright and license of `divsufsort.{h,c}` is not changed. --- Makefile | 3 +- doc/educational_decoder/Makefile | 3 +- doc/educational_decoder/harness.c | 3 +- doc/educational_decoder/zstd_decompress.c | 3 +- doc/educational_decoder/zstd_decompress.h | 3 +- examples/Makefile | 3 +- examples/common.h | 2 +- examples/dictionary_compression.c | 2 +- examples/dictionary_decompression.c | 2 +- examples/multiple_simple_compression.c | 2 +- examples/multiple_streaming_compression.c | 2 +- examples/simple_compression.c | 2 +- examples/simple_decompression.c | 2 +- examples/streaming_compression.c | 2 +- examples/streaming_decompression.c | 2 +- examples/streaming_memory_usage.c | 2 +- lib/Makefile | 3 +- lib/common/bitstream.h | 42 ++++++--------------- lib/common/compiler.h | 2 +- lib/common/cpu.h | 2 +- lib/common/debug.c | 42 ++++++--------------- lib/common/debug.h | 42 ++++++--------------- lib/common/entropy_common.c | 46 +++++++---------------- lib/common/error_private.c | 2 +- lib/common/error_private.h | 2 +- lib/common/fse.h | 42 ++++++--------------- lib/common/fse_decompress.c | 42 ++++++--------------- lib/common/huf.h | 42 ++++++--------------- lib/common/mem.h | 2 +- lib/common/pool.c | 2 +- lib/common/pool.h | 2 +- lib/common/threading.c | 7 ++-- lib/common/threading.h | 7 ++-- lib/common/xxhash.c | 42 ++++++--------------- lib/common/xxhash.h | 42 ++++++--------------- lib/common/zstd_common.c | 2 +- lib/common/zstd_errors.h | 2 +- lib/common/zstd_internal.h | 2 +- lib/compress/fse_compress.c | 42 ++++++--------------- lib/compress/hist.c | 44 ++++++---------------- lib/compress/hist.h | 44 ++++++---------------- lib/compress/huf_compress.c | 42 ++++++--------------- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_compress_internal.h | 2 +- lib/compress/zstd_compress_literals.c | 2 +- lib/compress/zstd_compress_literals.h | 2 +- lib/compress/zstd_compress_sequences.c | 2 +- lib/compress/zstd_compress_sequences.h | 2 +- lib/compress/zstd_compress_superblock.c | 2 +- lib/compress/zstd_compress_superblock.h | 2 +- lib/compress/zstd_cwksp.h | 2 +- lib/compress/zstd_double_fast.c | 2 +- lib/compress/zstd_double_fast.h | 2 +- lib/compress/zstd_fast.c | 2 +- lib/compress/zstd_fast.h | 2 +- lib/compress/zstd_lazy.c | 2 +- lib/compress/zstd_lazy.h | 2 +- lib/compress/zstd_ldm.c | 3 +- lib/compress/zstd_ldm.h | 3 +- lib/compress/zstd_opt.c | 2 +- lib/compress/zstd_opt.h | 2 +- lib/compress/zstdmt_compress.c | 2 +- lib/compress/zstdmt_compress.h | 2 +- lib/decompress/huf_decompress.c | 42 ++++++--------------- lib/decompress/zstd_ddict.c | 2 +- lib/decompress/zstd_ddict.h | 2 +- lib/decompress/zstd_decompress.c | 2 +- lib/decompress/zstd_decompress_block.c | 2 +- lib/decompress/zstd_decompress_block.h | 2 +- lib/decompress/zstd_decompress_internal.h | 2 +- lib/deprecated/zbuff.h | 2 +- lib/deprecated/zbuff_common.c | 2 +- lib/deprecated/zbuff_compress.c | 2 +- lib/deprecated/zbuff_decompress.c | 2 +- lib/dictBuilder/cover.c | 2 +- lib/dictBuilder/cover.h | 10 +++++ lib/dictBuilder/fastcover.c | 10 +++++ lib/dictBuilder/zdict.c | 2 +- lib/dictBuilder/zdict.h | 2 +- lib/dll/example/Makefile | 3 +- lib/legacy/zstd_legacy.h | 2 +- lib/legacy/zstd_v01.c | 2 +- lib/legacy/zstd_v01.h | 2 +- lib/legacy/zstd_v02.c | 2 +- lib/legacy/zstd_v02.h | 2 +- lib/legacy/zstd_v03.c | 2 +- lib/legacy/zstd_v03.h | 2 +- lib/legacy/zstd_v04.c | 2 +- lib/legacy/zstd_v04.h | 2 +- lib/legacy/zstd_v05.c | 2 +- lib/legacy/zstd_v05.h | 2 +- lib/legacy/zstd_v06.c | 2 +- lib/legacy/zstd_v06.h | 2 +- lib/legacy/zstd_v07.c | 2 +- lib/legacy/zstd_v07.h | 2 +- lib/zstd.h | 2 +- programs/Makefile | 3 +- programs/benchfn.c | 2 +- programs/benchfn.h | 2 +- programs/benchzstd.c | 2 +- programs/benchzstd.h | 2 +- programs/datagen.c | 2 +- programs/datagen.h | 2 +- programs/dibio.c | 2 +- programs/dibio.h | 2 +- programs/fileio.c | 2 +- programs/fileio.h | 2 +- programs/platform.h | 2 +- programs/timefn.c | 2 +- programs/timefn.h | 2 +- programs/util.c | 2 +- programs/util.h | 2 +- programs/windres/verrsrc.h | 9 +++++ programs/zstdcli.c | 2 +- tests/DEPRECATED-test-zstd-speed.py | 3 +- tests/Makefile | 3 +- tests/automated_benchmarking.py | 10 +++++ tests/bigdict.c | 2 +- tests/checkTag.c | 2 +- tests/datagencli.c | 2 +- tests/decodecorpus.c | 2 +- tests/fullbench.c | 2 +- tests/fuzz/Makefile | 3 +- tests/fuzz/block_decompress.c | 3 +- tests/fuzz/block_round_trip.c | 3 +- tests/fuzz/dictionary_decompress.c | 3 +- tests/fuzz/dictionary_loader.c | 3 +- tests/fuzz/dictionary_round_trip.c | 3 +- tests/fuzz/fuzz.h | 3 +- tests/fuzz/fuzz.py | 3 +- tests/fuzz/fuzz_data_producer.c | 3 +- tests/fuzz/fuzz_data_producer.h | 3 +- tests/fuzz/fuzz_helpers.h | 3 +- tests/fuzz/regression_driver.c | 3 +- tests/fuzz/simple_compress.c | 3 +- tests/fuzz/simple_decompress.c | 3 +- tests/fuzz/simple_round_trip.c | 3 +- tests/fuzz/stream_decompress.c | 3 +- tests/fuzz/stream_round_trip.c | 3 +- tests/fuzz/zstd_frame_info.c | 3 +- tests/fuzz/zstd_helpers.c | 3 +- tests/fuzz/zstd_helpers.h | 4 +- tests/fuzzer.c | 2 +- tests/gzip/Makefile | 3 +- tests/invalidDictionaries.c | 2 +- tests/legacy.c | 2 +- tests/longmatch.c | 2 +- tests/paramgrill.c | 2 +- tests/poolTests.c | 2 +- tests/rateLimiter.py | 3 +- tests/regression/Makefile | 3 +- tests/regression/config.c | 2 +- tests/regression/config.h | 2 +- tests/regression/data.c | 2 +- tests/regression/data.h | 2 +- tests/regression/levels.h | 2 +- tests/regression/method.c | 2 +- tests/regression/method.h | 2 +- tests/regression/result.c | 2 +- tests/regression/result.h | 2 +- tests/regression/test.c | 2 +- tests/roundTripCrash.c | 2 +- tests/seqgen.c | 2 +- tests/seqgen.h | 2 +- tests/test-zstd-versions.py | 3 +- tests/zbufftest.c | 2 +- tests/zstreamtest.c | 2 +- zlibWrapper/gzcompatibility.h | 2 +- zlibWrapper/zstd_zlibwrapper.c | 2 +- zlibWrapper/zstd_zlibwrapper.h | 2 +- 170 files changed, 392 insertions(+), 595 deletions(-) diff --git a/Makefile b/Makefile index 9b19d4d31a8..b1e3728e118 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2015-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ PRGDIR = programs diff --git a/doc/educational_decoder/Makefile b/doc/educational_decoder/Makefile index b49a08fd1e9..316c6eadc4a 100644 --- a/doc/educational_decoder/Makefile +++ b/doc/educational_decoder/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ ZSTD ?= zstd # note: requires zstd installation on local system diff --git a/doc/educational_decoder/harness.c b/doc/educational_decoder/harness.c index 2bbb619d050..1403a6ed655 100644 --- a/doc/educational_decoder/harness.c +++ b/doc/educational_decoder/harness.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #include diff --git a/doc/educational_decoder/zstd_decompress.c b/doc/educational_decoder/zstd_decompress.c index eb92af73053..605918b39f8 100644 --- a/doc/educational_decoder/zstd_decompress.c +++ b/doc/educational_decoder/zstd_decompress.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /// Zstandard educational decoder implementation diff --git a/doc/educational_decoder/zstd_decompress.h b/doc/educational_decoder/zstd_decompress.h index 74b18533850..2b44eee95ce 100644 --- a/doc/educational_decoder/zstd_decompress.h +++ b/doc/educational_decoder/zstd_decompress.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #include /* size_t */ diff --git a/examples/Makefile b/examples/Makefile index 65ea8abad5d..1ae6bce83d0 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ # This Makefile presumes libzstd is installed, using `sudo make install` diff --git a/examples/common.h b/examples/common.h index a714cbb72c3..4492c7e4efa 100644 --- a/examples/common.h +++ b/examples/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/dictionary_compression.c b/examples/dictionary_compression.c index 9efdb785c11..d9aad45a7b0 100644 --- a/examples/dictionary_compression.c +++ b/examples/dictionary_compression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020 Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/dictionary_decompression.c b/examples/dictionary_decompression.c index f683bbb4380..7e50986e37a 100644 --- a/examples/dictionary_decompression.c +++ b/examples/dictionary_decompression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/multiple_simple_compression.c b/examples/multiple_simple_compression.c index a44ac8b442f..e409467b226 100644 --- a/examples/multiple_simple_compression.c +++ b/examples/multiple_simple_compression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/multiple_streaming_compression.c b/examples/multiple_streaming_compression.c index ad98b1bd1b0..8a4dc96c112 100644 --- a/examples/multiple_streaming_compression.c +++ b/examples/multiple_streaming_compression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/simple_compression.c b/examples/simple_compression.c index 019a143d4c8..618080b338f 100644 --- a/examples/simple_compression.c +++ b/examples/simple_compression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/simple_decompression.c b/examples/simple_decompression.c index 1aa57c7b093..e108987c625 100644 --- a/examples/simple_decompression.c +++ b/examples/simple_decompression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/streaming_compression.c b/examples/streaming_compression.c index d0b04895f01..f0f1065b1d2 100644 --- a/examples/streaming_compression.c +++ b/examples/streaming_compression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/streaming_decompression.c b/examples/streaming_decompression.c index d26b45b34c7..26eda3441b7 100644 --- a/examples/streaming_decompression.c +++ b/examples/streaming_decompression.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/examples/streaming_memory_usage.c b/examples/streaming_memory_usage.c index 26835788abe..37dd660e4a6 100644 --- a/examples/streaming_memory_usage.c +++ b/examples/streaming_memory_usage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2017-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/Makefile b/lib/Makefile index fd1710cf1a0..fc7daf0804e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2015-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ # Version numbers diff --git a/lib/common/bitstream.h b/lib/common/bitstream.h index ff891ca8f39..37b99c01eed 100644 --- a/lib/common/bitstream.h +++ b/lib/common/bitstream.h @@ -1,35 +1,15 @@ /* ****************************************************************** - bitstream - Part of FSE library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * bitstream + * Part of FSE library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #ifndef BITSTREAM_H_MODULE #define BITSTREAM_H_MODULE diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 4213dfcf361..b51ba6ef5d4 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/cpu.h b/lib/common/cpu.h index 5f0923fc928..6e8a974f62d 100644 --- a/lib/common/cpu.h +++ b/lib/common/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Facebook, Inc. + * Copyright (c) 2018-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/debug.c b/lib/common/debug.c index 3ebdd1cb15a..f303f4a2e53 100644 --- a/lib/common/debug.c +++ b/lib/common/debug.c @@ -1,35 +1,15 @@ /* ****************************************************************** - debug - Part of FSE library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * debug + * Part of FSE library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ diff --git a/lib/common/debug.h b/lib/common/debug.h index b4fc89d4974..ac6224888d8 100644 --- a/lib/common/debug.h +++ b/lib/common/debug.h @@ -1,35 +1,15 @@ /* ****************************************************************** - debug - Part of FSE library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * debug + * Part of FSE library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ diff --git a/lib/common/entropy_common.c b/lib/common/entropy_common.c index b12944e1de9..9d3e4e8e36a 100644 --- a/lib/common/entropy_common.c +++ b/lib/common/entropy_common.c @@ -1,36 +1,16 @@ -/* - Common functions of New Generation Entropy library - Copyright (C) 2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -*************************************************************************** */ +/* ****************************************************************** + * Common functions of New Generation Entropy library + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ /* ************************************* * Dependencies diff --git a/lib/common/error_private.c b/lib/common/error_private.c index 7c1bb67a23f..39205844091 100644 --- a/lib/common/error_private.c +++ b/lib/common/error_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/error_private.h b/lib/common/error_private.h index 0d2fa7e34b0..78a9780debe 100644 --- a/lib/common/error_private.h +++ b/lib/common/error_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/fse.h b/lib/common/fse.h index a7553e3721c..ff54e70ea75 100644 --- a/lib/common/fse.h +++ b/lib/common/fse.h @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy codec - Public Prototypes declaration - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * FSE : Finite State Entropy codec + * Public Prototypes declaration + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #if defined (__cplusplus) diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c index 4f073789820..e85a3ba4456 100644 --- a/lib/common/fse_decompress.c +++ b/lib/common/fse_decompress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy decoder - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c + * FSE : Finite State Entropy decoder + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ diff --git a/lib/common/huf.h b/lib/common/huf.h index 4a87db5c162..0d27ccdba94 100644 --- a/lib/common/huf.h +++ b/lib/common/huf.h @@ -1,35 +1,15 @@ /* ****************************************************************** - huff0 huffman codec, - part of Finite State Entropy library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * huff0 huffman codec, + * part of Finite State Entropy library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ #if defined (__cplusplus) diff --git a/lib/common/mem.h b/lib/common/mem.h index 530d30c8f75..89c8aea7d22 100644 --- a/lib/common/mem.h +++ b/lib/common/mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/pool.c b/lib/common/pool.c index f575935076c..aa4b4de0d3f 100644 --- a/lib/common/pool.c +++ b/lib/common/pool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/pool.h b/lib/common/pool.h index 458d37f13c3..8503e2d2309 100644 --- a/lib/common/pool.h +++ b/lib/common/pool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/threading.c b/lib/common/threading.c index 482664bd9ad..e2edb313ebf 100644 --- a/lib/common/threading.c +++ b/lib/common/threading.c @@ -2,12 +2,13 @@ * Copyright (c) 2016 Tino Reichardt * All rights reserved. * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). - * - * You can contact the author at: - * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/lib/common/threading.h b/lib/common/threading.h index 3193ca7db86..fd0060d5aa2 100644 --- a/lib/common/threading.h +++ b/lib/common/threading.h @@ -2,12 +2,13 @@ * Copyright (c) 2016 Tino Reichardt * All rights reserved. * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). - * - * You can contact the author at: - * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * You may select, at your option, one of the above-listed licenses. */ #ifndef THREADING_H_938743 diff --git a/lib/common/xxhash.c b/lib/common/xxhash.c index 99d24596218..429a869e9a4 100644 --- a/lib/common/xxhash.c +++ b/lib/common/xxhash.c @@ -1,35 +1,15 @@ /* -* xxHash - Fast Hash algorithm -* Copyright (C) 2012-2016, Yann Collet -* -* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* You can contact the author at : -* - xxHash homepage: http://www.xxhash.com -* - xxHash source repository : https://github.com/Cyan4973/xxHash + * xxHash - Fast Hash algorithm + * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - xxHash homepage: http://www.xxhash.com + * - xxHash source repository : https://github.com/Cyan4973/xxHash + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ diff --git a/lib/common/xxhash.h b/lib/common/xxhash.h index 9bad1f59f63..4207eba8328 100644 --- a/lib/common/xxhash.h +++ b/lib/common/xxhash.h @@ -1,35 +1,15 @@ /* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : https://github.com/Cyan4973/xxHash + * xxHash - Extremely Fast Hash algorithm + * Header File + * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - xxHash source repository : https://github.com/Cyan4973/xxHash + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /* Notice extracted from xxHash homepage : diff --git a/lib/common/zstd_common.c b/lib/common/zstd_common.c index 667f4a27fc6..91fe3323a5b 100644 --- a/lib/common/zstd_common.c +++ b/lib/common/zstd_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/zstd_errors.h b/lib/common/zstd_errors.h index 92a3433896c..238309457b3 100644 --- a/lib/common/zstd_errors.h +++ b/lib/common/zstd_errors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 04d2ac80d8a..ce80f8c5639 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c index 68b47e10935..c8bbd778a23 100644 --- a/lib/compress/fse_compress.c +++ b/lib/compress/fse_compress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - FSE : Finite State Entropy encoder - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c + * FSE : Finite State Entropy encoder + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* ************************************************************** diff --git a/lib/compress/hist.c b/lib/compress/hist.c index 45b7babc1e2..c17b9725f0d 100644 --- a/lib/compress/hist.c +++ b/lib/compress/hist.c @@ -1,36 +1,16 @@ /* ****************************************************************** - hist : Histogram functions - part of Finite State Entropy project - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c + * hist : Histogram functions + * part of Finite State Entropy project + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* --- dependencies --- */ diff --git a/lib/compress/hist.h b/lib/compress/hist.h index 8b389358dc1..77e3ec4fb19 100644 --- a/lib/compress/hist.h +++ b/lib/compress/hist.h @@ -1,36 +1,16 @@ /* ****************************************************************** - hist : Histogram functions - part of Finite State Entropy project - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c + * hist : Histogram functions + * part of Finite State Entropy project + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* --- dependencies --- */ diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index b8e6fb38676..bfc5e6efd29 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - Huffman encoder, part of New Generation Entropy library - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c + * Huffman encoder, part of New Generation Entropy library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* ************************************************************** diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 69ee7275939..bb0a600729f 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 0d54652fa30..95e1a52edd0 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c index df3f269ded6..8d22bcadffb 100644 --- a/lib/compress/zstd_compress_literals.c +++ b/lib/compress/zstd_compress_literals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_literals.h b/lib/compress/zstd_compress_literals.h index 97273d7cfdb..8b087057432 100644 --- a/lib/compress/zstd_compress_literals.h +++ b/lib/compress/zstd_compress_literals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index b69221e63b2..07a03c8a3ae 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index 10cf678151a..b884e45b42e 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 39af1aba710..8c98d18e151 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h index 099ad3bb8f1..3bd6fdcf33e 100644 --- a/lib/compress/zstd_compress_superblock.h +++ b/lib/compress/zstd_compress_superblock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index fc9765bd3f3..2dfab3a4e3e 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 2e657f7c426..02515ee23b6 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h index 4fa31acfc0d..73a2002f3a3 100644 --- a/lib/compress/zstd_double_fast.h +++ b/lib/compress/zstd_double_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 09e220b3abc..aec518070e6 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h index b74a88c57c8..3e15cc85cdd 100644 --- a/lib/compress/zstd_fast.h +++ b/lib/compress/zstd_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index dd82830eaad..81cdbc96fdb 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_lazy.h b/lib/compress/zstd_lazy.h index bb1763069f3..581936f03bd 100644 --- a/lib/compress/zstd_lazy.h +++ b/lib/compress/zstd_lazy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index c3312ad3e3d..d9dd5a95f7e 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #include "zstd_ldm.h" diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index a47846128b2..7e3326c8c9d 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #ifndef ZSTD_LDM_H diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 14950622079..a835e9ec285 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstd_opt.h b/lib/compress/zstd_opt.h index 094f7476650..9aba8a9018c 100644 --- a/lib/compress/zstd_opt.h +++ b/lib/compress/zstd_opt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 4eaa3fcddea..fd6d9895946 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 12a526087db..b90fd389a41 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index e599070ae44..6cf9c4fddd2 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -1,35 +1,15 @@ /* ****************************************************************** - huff0 huffman decoder, - part of Finite State Entropy library - Copyright (C) 2013-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * huff0 huffman decoder, + * part of Finite State Entropy library + * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ /* ************************************************************** diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index 0af3d23bfe2..e931597d80b 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/zstd_ddict.h b/lib/decompress/zstd_ddict.h index 0479d11bb03..3ab7532ee3e 100644 --- a/lib/decompress/zstd_ddict.h +++ b/lib/decompress/zstd_ddict.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index f87e2618418..1770476a6d8 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 9d60fdf30dd..521daa3d14c 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/zstd_decompress_block.h b/lib/decompress/zstd_decompress_block.h index 7e929604102..a065f8d930a 100644 --- a/lib/decompress/zstd_decompress_block.h +++ b/lib/decompress/zstd_decompress_block.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 99eab854ce1..059c8194032 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff.h b/lib/deprecated/zbuff.h index 04183eab98f..7686f76a46a 100644 --- a/lib/deprecated/zbuff.h +++ b/lib/deprecated/zbuff.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_common.c b/lib/deprecated/zbuff_common.c index 661b9b0e18c..e2b9613f062 100644 --- a/lib/deprecated/zbuff_common.c +++ b/lib/deprecated/zbuff_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_compress.c b/lib/deprecated/zbuff_compress.c index f39c60d89f6..2d20b137759 100644 --- a/lib/deprecated/zbuff_compress.c +++ b/lib/deprecated/zbuff_compress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/deprecated/zbuff_decompress.c b/lib/deprecated/zbuff_decompress.c index 923c22b73c5..d3c49e84b81 100644 --- a/lib/deprecated/zbuff_decompress.c +++ b/lib/deprecated/zbuff_decompress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index 2e129dd9183..b57981c52b2 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/dictBuilder/cover.h b/lib/dictBuilder/cover.h index d9e0636a659..77943f0a715 100644 --- a/lib/dictBuilder/cover.h +++ b/lib/dictBuilder/cover.h @@ -1,3 +1,13 @@ +/* + * Copyright (c) 2017-2020, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + #include /* fprintf */ #include /* malloc, free, qsort */ #include /* memset */ diff --git a/lib/dictBuilder/fastcover.c b/lib/dictBuilder/fastcover.c index 941bb5a26ae..5bc9ca50fc2 100644 --- a/lib/dictBuilder/fastcover.c +++ b/lib/dictBuilder/fastcover.c @@ -1,3 +1,13 @@ +/* + * Copyright (c) 2018-2020, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + /*-************************************* * Dependencies ***************************************/ diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 344ab446b9d..6fa1ca69910 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index 1313bd21448..53f58d7ac2f 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/dll/example/Makefile b/lib/dll/example/Makefile index 45d0db3cd54..8f19195595b 100644 --- a/lib/dll/example/Makefile +++ b/lib/dll/example/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ VOID := /dev/null diff --git a/lib/legacy/zstd_legacy.h b/lib/legacy/zstd_legacy.h index 0dbd3c7a40f..ecd968212eb 100644 --- a/lib/legacy/zstd_legacy.h +++ b/lib/legacy/zstd_legacy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index 8112527f058..f8eb21db8a3 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v01.h b/lib/legacy/zstd_v01.h index 245f9dd3146..7910351726c 100644 --- a/lib/legacy/zstd_v01.h +++ b/lib/legacy/zstd_v01.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index c8783799b9c..dc4a3e8a863 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v02.h b/lib/legacy/zstd_v02.h index 9d7d8d9b5bc..5f8f6cd60cc 100644 --- a/lib/legacy/zstd_v02.h +++ b/lib/legacy/zstd_v02.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 162bd63024d..f0c26b8eb18 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v03.h b/lib/legacy/zstd_v03.h index efd8c2b9241..5fc72730ce9 100644 --- a/lib/legacy/zstd_v03.h +++ b/lib/legacy/zstd_v03.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index 0150c9fb482..bf344543846 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v04.h b/lib/legacy/zstd_v04.h index bb5f3b7d0b8..15fce0d487f 100644 --- a/lib/legacy/zstd_v04.h +++ b/lib/legacy/zstd_v04.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index aa564b415b9..07355ecb6cc 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v05.h b/lib/legacy/zstd_v05.h index 4a979854b36..6c46e8f23aa 100644 --- a/lib/legacy/zstd_v05.h +++ b/lib/legacy/zstd_v05.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index d5d778fce14..b957e5b0ce2 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v06.h b/lib/legacy/zstd_v06.h index 07818571dca..2fd99e629d4 100644 --- a/lib/legacy/zstd_v06.h +++ b/lib/legacy/zstd_v06.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index 14a93655e19..1a93bb93d8f 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/legacy/zstd_v07.h b/lib/legacy/zstd_v07.h index a566c1d102a..9da50c4e641 100644 --- a/lib/legacy/zstd_v07.h +++ b/lib/legacy/zstd_v07.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/lib/zstd.h b/lib/zstd.h index fcd50986415..6da84e27098 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/Makefile b/programs/Makefile index 47d3965cfca..8146732b507 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2015-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ########################################################################## # zstd : Command Line Utility, supporting gzip-like arguments # zstd32 : Same as zstd, but forced to compile in 32-bits mode diff --git a/programs/benchfn.c b/programs/benchfn.c index 2a51a34ff11..ed7273afb6e 100644 --- a/programs/benchfn.c +++ b/programs/benchfn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/benchfn.h b/programs/benchfn.h index 19e056581a5..e555bbe6ae3 100644 --- a/programs/benchfn.h +++ b/programs/benchfn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 925a570b1a5..80e98050c7f 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/benchzstd.h b/programs/benchzstd.h index ef7d9fb1114..99fae56a01a 100644 --- a/programs/benchzstd.h +++ b/programs/benchzstd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/datagen.c b/programs/datagen.c index ead9b2d2415..7cf83bdaa4a 100644 --- a/programs/datagen.c +++ b/programs/datagen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/datagen.h b/programs/datagen.h index 2fcc980e5e7..5a2682d8f9f 100644 --- a/programs/datagen.h +++ b/programs/datagen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/dibio.c b/programs/dibio.c index ea4bb4bf1f3..2b322b639cc 100644 --- a/programs/dibio.c +++ b/programs/dibio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/dibio.h b/programs/dibio.h index ea163fe6afd..436bddbb503 100644 --- a/programs/dibio.h +++ b/programs/dibio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/fileio.c b/programs/fileio.c index c833336dc8a..b8194ad6132 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/fileio.h b/programs/fileio.h index 64a7035b183..565cbae117c 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/platform.h b/programs/platform.h index 31820631eea..2b4b9f2d867 100644 --- a/programs/platform.h +++ b/programs/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/timefn.c b/programs/timefn.c index 8d92b3a70c7..95460d0d971 100644 --- a/programs/timefn.c +++ b/programs/timefn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2019-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/timefn.h b/programs/timefn.h index 7636f1f4d1b..eb3c130934e 100644 --- a/programs/timefn.h +++ b/programs/timefn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/util.c b/programs/util.c index 4a3a3766005..ab1abd3b186 100644 --- a/programs/util.c +++ b/programs/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/util.h b/programs/util.h index 95cc9c6044a..40200729adb 100644 --- a/programs/util.h +++ b/programs/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/programs/windres/verrsrc.h b/programs/windres/verrsrc.h index e282add025a..98156480ffd 100644 --- a/programs/windres/verrsrc.h +++ b/programs/windres/verrsrc.h @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ /* minimal set of defines required to generate zstd.res from zstd.rc */ #define VS_VERSION_INFO 1 diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 8e86c282b17..5eb561c1858 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/DEPRECATED-test-zstd-speed.py b/tests/DEPRECATED-test-zstd-speed.py index 1f6c8a7cde9..b3f80745984 100755 --- a/tests/DEPRECATED-test-zstd-speed.py +++ b/tests/DEPRECATED-test-zstd-speed.py @@ -2,12 +2,13 @@ # THIS BENCHMARK IS BEING REPLACED BY automated-bencmarking.py # ################################################################ -# Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. +# Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ########################################################################## # Limitations: diff --git a/tests/Makefile b/tests/Makefile index bcc84ddf1de..3d007471085 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2015-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ # datagen : Synthetic and parametrable data generator, for tests # fullbench : Precisely measure speed for each zstd inner functions diff --git a/tests/automated_benchmarking.py b/tests/automated_benchmarking.py index 50140e9fd1d..d0cfb1fbe37 100644 --- a/tests/automated_benchmarking.py +++ b/tests/automated_benchmarking.py @@ -1,3 +1,13 @@ +# ################################################################ +# Copyright (c) 2020-2020, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under both the BSD-style license (found in the +# LICENSE file in the root directory of this source tree) and the GPLv2 (found +# in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. +# ########################################################################## + import argparse import glob import json diff --git a/tests/bigdict.c b/tests/bigdict.c index 11501f6df0f..aeda56cb538 100644 --- a/tests/bigdict.c +++ b/tests/bigdict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2017-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/checkTag.c b/tests/checkTag.c index fda3fd1f9df..90af24ab14a 100644 --- a/tests/checkTag.c +++ b/tests/checkTag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2018-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/datagencli.c b/tests/datagencli.c index 6c1dd4719ed..713ca9963e0 100644 --- a/tests/datagencli.c +++ b/tests/datagencli.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index 91873ba4603..af961bfd0c7 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2017-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/fullbench.c b/tests/fullbench.c index be49b1428ff..5eccfc5594b 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index f66dadef041..a7f3a73a068 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2016-present, Facebook, Inc. +# Copyright (c) 2016-2020, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ # Optionally user defined flags diff --git a/tests/fuzz/block_decompress.c b/tests/fuzz/block_decompress.c index a904b44624d..f2a280b6ca9 100644 --- a/tests/fuzz/block_decompress.c +++ b/tests/fuzz/block_decompress.c @@ -1,10 +1,11 @@ /** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/block_round_trip.c b/tests/fuzz/block_round_trip.c index 89f060a6eb3..8048cb263c3 100644 --- a/tests/fuzz/block_round_trip.c +++ b/tests/fuzz/block_round_trip.c @@ -1,10 +1,11 @@ /** - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/dictionary_decompress.c b/tests/fuzz/dictionary_decompress.c index 9cc69fa3786..139c90af3a2 100644 --- a/tests/fuzz/dictionary_decompress.c +++ b/tests/fuzz/dictionary_decompress.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/dictionary_loader.c b/tests/fuzz/dictionary_loader.c index cb34f5d22d9..014d6b85962 100644 --- a/tests/fuzz/dictionary_loader.c +++ b/tests/fuzz/dictionary_loader.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/dictionary_round_trip.c b/tests/fuzz/dictionary_round_trip.c index 4a32b82be78..a0e7037c0ea 100644 --- a/tests/fuzz/dictionary_round_trip.c +++ b/tests/fuzz/dictionary_round_trip.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/fuzz.h b/tests/fuzz/fuzz.h index 6d53aa6d5c7..8ee96453674 100644 --- a/tests/fuzz/fuzz.h +++ b/tests/fuzz/fuzz.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/fuzz.py b/tests/fuzz/fuzz.py index 87f115afde9..52d41d2be37 100755 --- a/tests/fuzz/fuzz.py +++ b/tests/fuzz/fuzz.py @@ -1,12 +1,13 @@ #!/usr/bin/env python # ################################################################ -# Copyright (c) 2016-present, Facebook, Inc. +# Copyright (c) 2016-2020, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ########################################################################## import argparse diff --git a/tests/fuzz/fuzz_data_producer.c b/tests/fuzz/fuzz_data_producer.c index b465337eac3..00bb0a3b21b 100644 --- a/tests/fuzz/fuzz_data_producer.c +++ b/tests/fuzz/fuzz_data_producer.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #include "fuzz_data_producer.h" diff --git a/tests/fuzz/fuzz_data_producer.h b/tests/fuzz/fuzz_data_producer.h index f2b609677d7..41e0b52d5d1 100644 --- a/tests/fuzz/fuzz_data_producer.h +++ b/tests/fuzz/fuzz_data_producer.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/fuzz_helpers.h b/tests/fuzz/fuzz_helpers.h index 3de917fd126..1420a65d2ce 100644 --- a/tests/fuzz/fuzz_helpers.h +++ b/tests/fuzz/fuzz_helpers.h @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/regression_driver.c b/tests/fuzz/regression_driver.c index b3c5fba68e1..8180ca822fc 100644 --- a/tests/fuzz/regression_driver.c +++ b/tests/fuzz/regression_driver.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #include "fuzz.h" diff --git a/tests/fuzz/simple_compress.c b/tests/fuzz/simple_compress.c index 487be3a354c..f155e3b1c38 100644 --- a/tests/fuzz/simple_compress.c +++ b/tests/fuzz/simple_compress.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/simple_decompress.c b/tests/fuzz/simple_decompress.c index 6182746a1d1..8c404d13900 100644 --- a/tests/fuzz/simple_decompress.c +++ b/tests/fuzz/simple_decompress.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c index 6a65b19087e..e37fa6f6f61 100644 --- a/tests/fuzz/simple_round_trip.c +++ b/tests/fuzz/simple_round_trip.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/stream_decompress.c b/tests/fuzz/stream_decompress.c index aff9fcec785..df3b009aee8 100644 --- a/tests/fuzz/stream_decompress.c +++ b/tests/fuzz/stream_decompress.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/stream_round_trip.c b/tests/fuzz/stream_round_trip.c index 810ed05eb9f..e060950f016 100644 --- a/tests/fuzz/stream_round_trip.c +++ b/tests/fuzz/stream_round_trip.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/zstd_frame_info.c b/tests/fuzz/zstd_frame_info.c index 359cf128f5b..16a28d6903a 100644 --- a/tests/fuzz/zstd_frame_info.c +++ b/tests/fuzz/zstd_frame_info.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /** diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c index 313b463f783..8294f6fe235 100644 --- a/tests/fuzz/zstd_helpers.c +++ b/tests/fuzz/zstd_helpers.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ #define ZSTD_STATIC_LINKING_ONLY diff --git a/tests/fuzz/zstd_helpers.h b/tests/fuzz/zstd_helpers.h index 2210bcaf8f5..6a4e340d358 100644 --- a/tests/fuzz/zstd_helpers.h +++ b/tests/fuzz/zstd_helpers.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2016-present, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ - /** * Helper functions for fuzzing. */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 3c4aac7a8fc..1333ec9b43c 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/gzip/Makefile b/tests/gzip/Makefile index c5d67206b99..73f62f0ebf0 100644 --- a/tests/gzip/Makefile +++ b/tests/gzip/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2017-present, Facebook, Inc. +# Copyright (c) 2017-2020, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ PRGDIR = ../../programs diff --git a/tests/invalidDictionaries.c b/tests/invalidDictionaries.c index b23db036f48..23e93fd5409 100644 --- a/tests/invalidDictionaries.c +++ b/tests/invalidDictionaries.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/legacy.c b/tests/legacy.c index eb329203833..3d3ec43581f 100644 --- a/tests/legacy.c +++ b/tests/legacy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/longmatch.c b/tests/longmatch.c index b673baa6014..93e78dd1fc5 100644 --- a/tests/longmatch.c +++ b/tests/longmatch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2017-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/paramgrill.c b/tests/paramgrill.c index 98fb313783a..e9cc2a94e89 100644 --- a/tests/paramgrill.c +++ b/tests/paramgrill.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/poolTests.c b/tests/poolTests.c index 02ec62af9f3..e1576ba85bf 100644 --- a/tests/poolTests.c +++ b/tests/poolTests.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/rateLimiter.py b/tests/rateLimiter.py index da0baf01464..1068c44248f 100755 --- a/tests/rateLimiter.py +++ b/tests/rateLimiter.py @@ -1,12 +1,13 @@ #!/usr/bin/env python3 # ################################################################ -# Copyright (c) 2018-present, Facebook, Inc. +# Copyright (c) 2018-2020, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ########################################################################## # Rate limiter, replacement for pv diff --git a/tests/regression/Makefile b/tests/regression/Makefile index 03e5b0af1d7..87c1c2b966f 100644 --- a/tests/regression/Makefile +++ b/tests/regression/Makefile @@ -1,10 +1,11 @@ # ################################################################ -# Copyright (c) 2015-present, Facebook, Inc. +# Copyright (c) 2015-2020, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ CFLAGS ?= -O3 diff --git a/tests/regression/config.c b/tests/regression/config.c index b82482f4612..ed6b692352c 100644 --- a/tests/regression/config.c +++ b/tests/regression/config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/config.h b/tests/regression/config.h index 3cd0308a098..aa563b9e903 100644 --- a/tests/regression/config.h +++ b/tests/regression/config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/data.c b/tests/regression/data.c index 631a6f27f57..b75ac11928d 100644 --- a/tests/regression/data.c +++ b/tests/regression/data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/data.h b/tests/regression/data.h index 2de8134f52a..90ed22f19dc 100644 --- a/tests/regression/data.h +++ b/tests/regression/data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/levels.h b/tests/regression/levels.h index f9668907512..5e7d40a7d0e 100644 --- a/tests/regression/levels.h +++ b/tests/regression/levels.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/method.c b/tests/regression/method.c index b74f548196f..3c949a278d3 100644 --- a/tests/regression/method.c +++ b/tests/regression/method.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/method.h b/tests/regression/method.h index d70b776b1b9..6884e54186e 100644 --- a/tests/regression/method.h +++ b/tests/regression/method.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/result.c b/tests/regression/result.c index 31439b08cde..2911722cd5a 100644 --- a/tests/regression/result.c +++ b/tests/regression/result.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/result.h b/tests/regression/result.h index 8c80cf85a96..0085c2adf13 100644 --- a/tests/regression/result.h +++ b/tests/regression/result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/regression/test.c b/tests/regression/test.c index 812893b2730..ff2cdba3063 100644 --- a/tests/regression/test.c +++ b/tests/regression/test.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/roundTripCrash.c b/tests/roundTripCrash.c index 3de5933185d..c117d2c268a 100644 --- a/tests/roundTripCrash.c +++ b/tests/roundTripCrash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/seqgen.c b/tests/seqgen.c index 06e3ed5ba0b..29c0c40545a 100644 --- a/tests/seqgen.c +++ b/tests/seqgen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/seqgen.h b/tests/seqgen.h index 72d798846aa..808099ba9fb 100644 --- a/tests/seqgen.h +++ b/tests/seqgen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-2020, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/test-zstd-versions.py b/tests/test-zstd-versions.py index 8e88b869b0d..fa217175271 100755 --- a/tests/test-zstd-versions.py +++ b/tests/test-zstd-versions.py @@ -2,12 +2,13 @@ """Test zstd interoperability between versions""" # ################################################################ -# Copyright (c) 2016-present, Yann Collet, Facebook, Inc. +# Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. # All rights reserved. # # This source code is licensed under both the BSD-style license (found in the # LICENSE file in the root directory of this source tree) and the GPLv2 (found # in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. # ################################################################ import filecmp diff --git a/tests/zbufftest.c b/tests/zbufftest.c index f01d89e51c4..cd3706af442 100644 --- a/tests/zbufftest.c +++ b/tests/zbufftest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2015-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 890e66f9ecb..a945125ac99 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/zlibWrapper/gzcompatibility.h b/zlibWrapper/gzcompatibility.h index ea8d50c8238..394648abbba 100644 --- a/zlibWrapper/gzcompatibility.h +++ b/zlibWrapper/gzcompatibility.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/zlibWrapper/zstd_zlibwrapper.c b/zlibWrapper/zstd_zlibwrapper.c index 3fa442106f1..4d2c7be5b44 100644 --- a/zlibWrapper/zstd_zlibwrapper.c +++ b/zlibWrapper/zstd_zlibwrapper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the diff --git a/zlibWrapper/zstd_zlibwrapper.h b/zlibWrapper/zstd_zlibwrapper.h index f828d3191b8..e791043e1d0 100644 --- a/zlibWrapper/zstd_zlibwrapper.h +++ b/zlibWrapper/zstd_zlibwrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the From 1f144351b76bf0a228dcee04a042e40d05b9c0d9 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 26 Mar 2020 16:57:48 -0700 Subject: [PATCH 248/402] [test] Add a test that checks for valid copyright and licenses Tests all `.h`, `.c`, `.py`, and `Makefile` files for valid copyright and license lines. Excludes a small number of exceptions (threading, and divsufsort). * Copyright does not contains `present` * Copyright contains `Facebook, Inc` * Copyright contains the current year * License contains exactly the lines we expect --- tests/test-license.py | 141 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 tests/test-license.py diff --git a/tests/test-license.py b/tests/test-license.py new file mode 100755 index 00000000000..522884dba31 --- /dev/null +++ b/tests/test-license.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 + +# ################################################################ +# Copyright (c) 2016-2020, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under both the BSD-style license (found in the +# LICENSE file in the root directory of this source tree) and the GPLv2 (found +# in the COPYING file in the root directory of this source tree). +# You may select, at your option, one of the above-listed licenses. +# ################################################################ + +import datetime +import enum +import glob +import os +import sys + +YEAR = datetime.datetime.now().year + +YEAR_STR = str(YEAR) + +ROOT = os.path.join(os.path.dirname(__file__), "..") + +RELDIRS = [ + "doc", + "examples", + "lib", + "programs", + "tests", +] + +DIRS = [os.path.join(ROOT, d) for d in RELDIRS] + +class File(enum.Enum): + C = 1 + H = 2 + MAKE = 3 + PY = 4 + +SUFFIX = { + File.C: ".c", + File.H: ".h", + File.MAKE: "Makefile", + File.PY: ".py", +} + +# License should certainly be in the first 10 KB. +MAX_BYTES = 10000 +MAX_LINES = 50 + +LICENSE_LINES = [ + "This source code is licensed under both the BSD-style license (found in the", + "LICENSE file in the root directory of this source tree) and the GPLv2 (found", + "in the COPYING file in the root directory of this source tree).", + "You may select, at your option, one of the above-listed licenses.", +] + +COPYRIGHT_EXCEPTIONS = { + # From zstdmt + "threading.c", + "threading.h", + # From divsufsort + "divsufsort.c", + "divsufsort.h", +} + +LICENSE_EXCEPTIONS = { + # From divsufsort + "divsufsort.c", + "divsufsort.h", +} + + +def valid_copyright(lines): + for line in lines: + line = line.strip() + if "Copyright" not in line: + continue + if "present" in line: + return (False, f"Copyright line '{line}' contains 'present'!") + if "Facebook, Inc" not in line: + return (False, f"Copyright line '{line}' does not contain 'Facebook, Inc'") + if YEAR_STR not in line: + return (False, f"Copyright line '{line}' does not contain {YEAR}") + if " (c) " not in line: + return (False, f"Copyright line '{line}' does not contain ' (c) '!") + return (True, "") + return (False, "Copyright not found!") + + +def valid_license(lines): + for b in range(len(lines)): + if LICENSE_LINES[0] not in lines[b]: + continue + for l in range(len(LICENSE_LINES)): + if LICENSE_LINES[l] not in lines[b + l]: + message = f"""Invalid license line found starting on line {b + l}! +Expected: '{LICENSE_LINES[l]}' +Actual: '{lines[b + l]}'""" + return (False, message) + return (True, "") + return (False, "License not found!") + + +def valid_file(filename): + with open(filename, "r") as f: + lines = f.readlines(MAX_BYTES) + lines = lines[:min(len(lines), MAX_LINES)] + + ok = True + if os.path.basename(filename) not in COPYRIGHT_EXCEPTIONS: + c_ok, c_msg = valid_copyright(lines) + if not c_ok: + print(f"{filename}: {c_msg}") + ok = False + if os.path.basename(filename) not in LICENSE_EXCEPTIONS: + l_ok, l_msg = valid_license(lines) + if not l_ok: + print(f"{filename}: {l_msg}") + ok = False + return ok + + +def main(): + invalid_files = [] + for directory in DIRS: + for suffix in SUFFIX.values(): + files = set(glob.glob(f"{directory}/*{suffix}")) + files |= set(glob.glob(f"{directory}/**/*{suffix}")) + for filename in files: + if not valid_file(filename): + invalid_files.append(filename) + if len(invalid_files) > 0: + print(f"Invalid files: {invalid_files}") + else: + print("Pass!") + return len(invalid_files) + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From ef9e6fe2270bc1d9a9886fd064026dd7c1225695 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 26 Mar 2020 15:04:15 -0700 Subject: [PATCH 249/402] [test] Fix playTests.sh with space in binary path playTests.sh didn't work when `ZSTD_BIN` or `DATAGEN_BIN` had a space in the path name. This happens for me because I split the cmake build directory by compiler name, like "Clang 9.0.0". The fix is to replace all instances of `$ZSTD` with the `zstd()` function, and the replace `$DATAGEN` with `datagen()`. This will allow us to change how we call zstd/datagen in the future without having to change every callsite. --- tests/playTests.sh | 857 +++++++++++++++++++++++---------------------- 1 file changed, 437 insertions(+), 420 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index c020127fe59..7a21376bd29 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -7,6 +7,26 @@ die() { exit 1 } +datagen() { + "$DATAGEN_BIN" $@ +} + +zstd() { + if [ -z "$EXEC_PREFIX" ]; then + "$ZSTD_BIN" $@ + else + "$EXEC_PREFIX" "$ZSTD_BIN" $@ + fi +} + +sudoZstd() { + if [ -z "$EXEC_PREFIX" ]; then + sudo "$ZSTD_BIN" $@ + else + sudo "$EXEC_PREFIX" "$ZSTD_BIN" $@ + fi +} + roundTripTest() { if [ -n "$3" ]; then cLevel="$3" @@ -22,9 +42,9 @@ roundTripTest() { fi rm -f tmp1 tmp2 - println "roundTripTest: $DATAGEN $1 $proba | $ZSTD -v$cLevel | $ZSTD -d$dLevel" - $DATAGEN $1 $proba | $MD5SUM > tmp1 - $DATAGEN $1 $proba | $ZSTD --ultra -v$cLevel | $ZSTD -d$dLevel | $MD5SUM > tmp2 + println "roundTripTest: datagen $1 $proba | zstd -v$cLevel | zstd -d$dLevel" + datagen $1 $proba | $MD5SUM > tmp1 + datagen $1 $proba | zstd --ultra -v$cLevel | zstd -d$dLevel | $MD5SUM > tmp2 $DIFF -q tmp1 tmp2 } @@ -42,11 +62,11 @@ fileRoundTripTest() { local_d="$local_c" fi - rm -f tmp.zstd tmp.md5.1 tmp.md5.2 - println "fileRoundTripTest: $DATAGEN $1 $local_p > tmp && $ZSTD -v$local_c -c tmp | $ZSTD -d$local_d" - $DATAGEN $1 $local_p > tmp + rm -f tmp.zst tmp.md5.1 tmp.md5.2 + println "fileRoundTripTest: datagen $1 $local_p > tmp && zstd -v$local_c -c tmp | zstd -d$local_d" + datagen $1 $local_p > tmp < tmp $MD5SUM > tmp.md5.1 - $ZSTD --ultra -v$local_c -c tmp | $ZSTD -d$local_d | $MD5SUM > tmp.md5.2 + zstd --ultra -v$local_c -c tmp | zstd -d$local_d | $MD5SUM > tmp.md5.2 $DIFF -q tmp.md5.1 tmp.md5.2 } @@ -105,13 +125,10 @@ esac println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN'" -[ -n "$ZSTD_BIN" ] || die "ZSTD_BIN variable must be defined!" -[ -n "$DATAGEN_BIN" ] || die "DATAGEN_BIN variable must be defined!" - -ZSTD="$EXE_PREFIX $ZSTD_BIN" -DATAGEN="$DATAGEN_BIN" +[ -n "$ZSTD_BIN" ] || die "$ZSTD_BIN variable must be defined!" +[ -n "$DATAGEN_BIN" ] || die "$DATAGEN_BIN variable must be defined!" -if echo hello | $ZSTD -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled' +if echo hello | zstd -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled' then hasMT="" else @@ -122,115 +139,115 @@ fi println "\n===> simple tests " -$DATAGEN > tmp +datagen > tmp println "test : basic compression " -$ZSTD -f tmp # trivial compression case, creates tmp.zst +zstd -f tmp # trivial compression case, creates tmp.zst println "test : basic decompression" -$ZSTD -df tmp.zst # trivial decompression case (overwrites tmp) +zstd -df tmp.zst # trivial decompression case (overwrites tmp) println "test : too large compression level => auto-fix" -$ZSTD -99 -f tmp # too large compression level, automatic sized down -$ZSTD -5000000000 -f tmp && die "too large numeric value : must fail" +zstd -99 -f tmp # too large compression level, automatic sized down +zstd -5000000000 -f tmp && die "too large numeric value : must fail" println "test : --fast aka negative compression levels" -$ZSTD --fast -f tmp # == -1 -$ZSTD --fast=3 -f tmp # == -3 -$ZSTD --fast=200000 -f tmp # too low compression level, automatic fixed -$ZSTD --fast=5000000000 -f tmp && die "too large numeric value : must fail" -$ZSTD -c --fast=0 tmp > $INTOVOID && die "--fast must not accept value 0" +zstd --fast -f tmp # == -1 +zstd --fast=3 -f tmp # == -3 +zstd --fast=200000 -f tmp # too low compression level, automatic fixed +zstd --fast=5000000000 -f tmp && die "too large numeric value : must fail" +zstd -c --fast=0 tmp > $INTOVOID && die "--fast must not accept value 0" println "test : too large numeric argument" -$ZSTD --fast=9999999999 -f tmp && die "should have refused numeric value" +zstd --fast=9999999999 -f tmp && die "should have refused numeric value" println "test : set compression level with environment variable ZSTD_CLEVEL" -ZSTD_CLEVEL=12 $ZSTD -f tmp # positive compression level -ZSTD_CLEVEL=-12 $ZSTD -f tmp # negative compression level -ZSTD_CLEVEL=+12 $ZSTD -f tmp # valid: verbose '+' sign -ZSTD_CLEVEL='' $ZSTD -f tmp # empty env var, warn and revert to default setting -ZSTD_CLEVEL=- $ZSTD -f tmp # malformed env var, warn and revert to default setting -ZSTD_CLEVEL=a $ZSTD -f tmp # malformed env var, warn and revert to default setting -ZSTD_CLEVEL=+a $ZSTD -f tmp # malformed env var, warn and revert to default setting -ZSTD_CLEVEL=3a7 $ZSTD -f tmp # malformed env var, warn and revert to default setting -ZSTD_CLEVEL=50000000000 $ZSTD -f tmp # numeric value too large, warn and revert to default setting +ZSTD_CLEVEL=12 zstd -f tmp # positive compression level +ZSTD_CLEVEL=-12 zstd -f tmp # negative compression level +ZSTD_CLEVEL=+12 zstd -f tmp # valid: verbose '+' sign +ZSTD_CLEVEL='' zstd -f tmp # empty env var, warn and revert to default setting +ZSTD_CLEVEL=- zstd -f tmp # malformed env var, warn and revert to default setting +ZSTD_CLEVEL=a zstd -f tmp # malformed env var, warn and revert to default setting +ZSTD_CLEVEL=+a zstd -f tmp # malformed env var, warn and revert to default setting +ZSTD_CLEVEL=3a7 zstd -f tmp # malformed env var, warn and revert to default setting +ZSTD_CLEVEL=50000000000 zstd -f tmp # numeric value too large, warn and revert to default setting println "test : override ZSTD_CLEVEL with command line option" -ZSTD_CLEVEL=12 $ZSTD --fast=3 -f tmp # overridden by command line option +ZSTD_CLEVEL=12 zstd --fast=3 -f tmp # overridden by command line option println "test : compress to stdout" -$ZSTD tmp -c > tmpCompressed -$ZSTD tmp --stdout > tmpCompressed # long command format +zstd tmp -c > tmpCompressed +zstd tmp --stdout > tmpCompressed # long command format println "test : compress to named file" rm tmpCompressed -$ZSTD tmp -o tmpCompressed +zstd tmp -o tmpCompressed test -f tmpCompressed # file must be created println "test : -o must be followed by filename (must fail)" -$ZSTD tmp -of tmpCompressed && die "-o must be followed by filename " +zstd tmp -of tmpCompressed && die "-o must be followed by filename " println "test : force write, correct order" -$ZSTD tmp -fo tmpCompressed +zstd tmp -fo tmpCompressed println "test : forgotten argument" cp tmp tmp2 -$ZSTD tmp2 -fo && die "-o must be followed by filename " +zstd tmp2 -fo && die "-o must be followed by filename " println "test : implied stdout when input is stdin" -println bob | $ZSTD | $ZSTD -d +println bob | zstd | zstd -d if [ "$isTerminal" = true ]; then println "test : compressed data to terminal" -println bob | $ZSTD && die "should have refused : compressed data to terminal" +println bob | zstd && die "should have refused : compressed data to terminal" println "test : compressed data from terminal (a hang here is a test fail, zstd is wrongly waiting on data from terminal)" -$ZSTD -d > $INTOVOID && die "should have refused : compressed data from terminal" +zstd -d > $INTOVOID && die "should have refused : compressed data from terminal" fi println "test : null-length file roundtrip" -println -n '' | $ZSTD - --stdout | $ZSTD -d --stdout +println -n '' | zstd - --stdout | zstd -d --stdout println "test : ensure small file doesn't add 3-bytes null block" -$DATAGEN -g1 > tmp1 -$ZSTD tmp1 -c | wc -c | grep "14" -$ZSTD < tmp1 | wc -c | grep "14" +datagen -g1 > tmp1 +zstd tmp1 -c | wc -c | grep "14" +zstd < tmp1 | wc -c | grep "14" println "test : decompress file with wrong suffix (must fail)" -$ZSTD -d tmpCompressed && die "wrong suffix error not detected!" -$ZSTD -df tmp && die "should have refused : wrong extension" +zstd -d tmpCompressed && die "wrong suffix error not detected!" +zstd -df tmp && die "should have refused : wrong extension" println "test : decompress into stdout" -$ZSTD -d tmpCompressed -c > tmpResult # decompression using stdout -$ZSTD --decompress tmpCompressed -c > tmpResult -$ZSTD --decompress tmpCompressed --stdout > tmpResult +zstd -d tmpCompressed -c > tmpResult # decompression using stdout +zstd --decompress tmpCompressed -c > tmpResult +zstd --decompress tmpCompressed --stdout > tmpResult println "test : decompress from stdin into stdout" -$ZSTD -dc < tmp.zst > $INTOVOID # combine decompression, stdin & stdout -$ZSTD -dc - < tmp.zst > $INTOVOID -$ZSTD -d < tmp.zst > $INTOVOID # implicit stdout when stdin is used -$ZSTD -d - < tmp.zst > $INTOVOID +zstd -dc < tmp.zst > $INTOVOID # combine decompression, stdin & stdout +zstd -dc - < tmp.zst > $INTOVOID +zstd -d < tmp.zst > $INTOVOID # implicit stdout when stdin is used +zstd -d - < tmp.zst > $INTOVOID println "test : impose memory limitation (must fail)" -$ZSTD -d -f tmp.zst -M2K -c > $INTOVOID && die "decompression needs more memory than allowed" -$ZSTD -d -f tmp.zst --memlimit=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command -$ZSTD -d -f tmp.zst --memory=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command -$ZSTD -d -f tmp.zst --memlimit-decompress=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command +zstd -d -f tmp.zst -M2K -c > $INTOVOID && die "decompression needs more memory than allowed" +zstd -d -f tmp.zst --memlimit=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command +zstd -d -f tmp.zst --memory=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command +zstd -d -f tmp.zst --memlimit-decompress=2K -c > $INTOVOID && die "decompression needs more memory than allowed" # long command println "test : overwrite protection" -$ZSTD -q tmp && die "overwrite check failed!" +zstd -q tmp && die "overwrite check failed!" println "test : force overwrite" -$ZSTD -q -f tmp -$ZSTD -q --force tmp +zstd -q -f tmp +zstd -q --force tmp println "test : overwrite readonly file" rm -f tmpro tmpro.zst println foo > tmpro.zst println foo > tmpro chmod 400 tmpro.zst -$ZSTD -q tmpro && die "should have refused to overwrite read-only file" -$ZSTD -q -f tmpro +zstd -q tmpro && die "should have refused to overwrite read-only file" +zstd -q -f tmpro println "test: --no-progress flag" -$ZSTD tmpro -c --no-progress | $ZSTD -d -f -o "$INTOVOID" --no-progress -$ZSTD tmpro -cv --no-progress | $ZSTD -dv -f -o "$INTOVOID" --no-progress +zstd tmpro -c --no-progress | zstd -d -f -o "$INTOVOID" --no-progress +zstd tmpro -cv --no-progress | zstd -dv -f -o "$INTOVOID" --no-progress rm -f tmpro tmpro.zst println "test: overwrite input file (must fail)" -$ZSTD tmp -fo tmp && die "zstd compression overwrote the input file" -$ZSTD tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file" +zstd tmp -fo tmp && die "zstd compression overwrote the input file" +zstd tmp.zst -dfo tmp.zst && die "zstd decompression overwrote the input file" println "test: detect that input file does not exist" -$ZSTD nothere && die "zstd hasn't detected that input file does not exist" +zstd nothere && die "zstd hasn't detected that input file does not exist" println "test: --[no-]compress-literals" -$ZSTD tmp -c --no-compress-literals -1 | $ZSTD -t -$ZSTD tmp -c --no-compress-literals --fast=1 | $ZSTD -t -$ZSTD tmp -c --no-compress-literals -19 | $ZSTD -t -$ZSTD tmp -c --compress-literals -1 | $ZSTD -t -$ZSTD tmp -c --compress-literals --fast=1 | $ZSTD -t -$ZSTD tmp -c --compress-literals -19 | $ZSTD -t -$ZSTD -b --fast=1 -i0e1 tmp --compress-literals -$ZSTD -b --fast=1 -i0e1 tmp --no-compress-literals +zstd tmp -c --no-compress-literals -1 | zstd -t +zstd tmp -c --no-compress-literals --fast=1 | zstd -t +zstd tmp -c --no-compress-literals -19 | zstd -t +zstd tmp -c --compress-literals -1 | zstd -t +zstd tmp -c --compress-literals --fast=1 | zstd -t +zstd tmp -c --compress-literals -19 | zstd -t +zstd -b --fast=1 -i0e1 tmp --compress-literals +zstd -b --fast=1 -i0e1 tmp --no-compress-literals println "\n===> zstdgrep tests" -ln -sf $ZSTD_BIN zstdcat +ln -sf "$ZSTD_BIN" zstdcat rm -f tmp_grep echo "1234" > tmp_grep -$ZSTD -f tmp_grep +zstd -f tmp_grep lines=$(ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep tmp_grep.zst | wc -l) test 2 -eq $lines ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst && die "Should have failed" @@ -240,12 +257,12 @@ rm -f tmp_grep* println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir -$DATAGEN $size > precompressedFilterTestDir/input.5 -$DATAGEN $size > precompressedFilterTestDir/input.6 -$ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir -$DATAGEN $size > precompressedFilterTestDir/input.7 -$DATAGEN $size > precompressedFilterTestDir/input.8 -$ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir +datagen $size > precompressedFilterTestDir/input.5 +datagen $size > precompressedFilterTestDir/input.6 +zstd --exclude-compressed --long --rm -r precompressedFilterTestDir +datagen $size > precompressedFilterTestDir/input.7 +datagen $size > precompressedFilterTestDir/input.8 +zstd --exclude-compressed --long --rm -r precompressedFilterTestDir test ! -f precompressedFilterTestDir/input.5.zst.zst test ! -f precompressedFilterTestDir/input.6.zst.zst file1timestamp=`$MTIME precompressedFilterTestDir/input.5.zst` @@ -256,12 +273,12 @@ else println "Test is not successful" fi # File Extension check. -$DATAGEN $size > precompressedFilterTestDir/input.zstbar -$ZSTD --exclude-compressed --long --rm -r precompressedFilterTestDir -# ZSTD should compress input.zstbar +datagen $size > precompressedFilterTestDir/input.zstbar +zstd --exclude-compressed --long --rm -r precompressedFilterTestDir +# zstd should compress input.zstbar test -f precompressedFilterTestDir/input.zstbar.zst # Check without the --exclude-compressed flag -$ZSTD --long --rm -r precompressedFilterTestDir +zstd --long --rm -r precompressedFilterTestDir # Files should get compressed again without the --exclude-compressed flag. test -f precompressedFilterTestDir/input.5.zst.zst test -f precompressedFilterTestDir/input.6.zst.zst @@ -270,33 +287,33 @@ println "Test completed" println "\n===> recursive mode test " # combination of -r with empty list of input file -$ZSTD -c -r < tmp > tmp.zst +zstd -c -r < tmp > tmp.zst println "\n===> file removal" -$ZSTD -f --rm tmp +zstd -f --rm tmp test ! -f tmp # tmp should no longer be present -$ZSTD -f -d --rm tmp.zst +zstd -f -d --rm tmp.zst test ! -f tmp.zst # tmp.zst should no longer be present println "test : should quietly not remove non-regular file" println hello > tmp -$ZSTD tmp -f -o "$DEVDEVICE" 2>tmplog > "$INTOVOID" +zstd tmp -f -o "$DEVDEVICE" 2>tmplog > "$INTOVOID" grep -v "Refusing to remove non-regular file" tmplog rm -f tmplog -$ZSTD tmp -f -o "$INTOVOID" 2>&1 | grep -v "Refusing to remove non-regular file" +zstd tmp -f -o "$INTOVOID" 2>&1 | grep -v "Refusing to remove non-regular file" println "test : --rm on stdin" -println a | $ZSTD --rm > $INTOVOID # --rm should remain silent +println a | zstd --rm > $INTOVOID # --rm should remain silent rm tmp -$ZSTD -f tmp && die "tmp not present : should have failed" +zstd -f tmp && die "tmp not present : should have failed" test ! -f tmp.zst # tmp.zst should not be created println "test : -d -f do not delete destination when source is not present" touch tmp # create destination file -$ZSTD -d -f tmp.zst && die "attempt to decompress a non existing file" +zstd -d -f tmp.zst && die "attempt to decompress a non existing file" test -f tmp # destination file should still be present println "test : -f do not delete destination when source is not present" rm tmp # erase source file touch tmp.zst # create destination file -$ZSTD -f tmp && die "attempt to compress a non existing file" +zstd -f tmp && die "attempt to compress a non existing file" test -f tmp.zst # destination file should still be present rm -rf tmp* # may also erase tmp* directory from previous failed run @@ -306,7 +323,7 @@ println "\n===> decompression only tests " # older versions of zstd cli are not able to decode such corner case. # As a consequence, the zstd cli do not generate them, to maintain compatibility with older versions. dd bs=1048576 count=1 if=/dev/zero of=tmp -$ZSTD -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst" +zstd -d -o tmp1 "$TESTDIR/golden-decompression/rle-first-block.zst" $DIFF -s tmp1 tmp rm tmp* @@ -314,47 +331,47 @@ rm tmp* println "\n===> compress multiple files" println hello > tmp1 println world > tmp2 -$ZSTD tmp1 tmp2 -o "$INTOVOID" -f -$ZSTD tmp1 tmp2 -c | $ZSTD -t -$ZSTD tmp1 tmp2 -o tmp.zst +zstd tmp1 tmp2 -o "$INTOVOID" -f +zstd tmp1 tmp2 -c | zstd -t +zstd tmp1 tmp2 -o tmp.zst test ! -f tmp1.zst test ! -f tmp2.zst -$ZSTD tmp1 tmp2 -$ZSTD -t tmp1.zst tmp2.zst -$ZSTD -dc tmp1.zst tmp2.zst -$ZSTD tmp1.zst tmp2.zst -o "$INTOVOID" -f -$ZSTD -d tmp1.zst tmp2.zst -o tmp +zstd tmp1 tmp2 +zstd -t tmp1.zst tmp2.zst +zstd -dc tmp1.zst tmp2.zst +zstd tmp1.zst tmp2.zst -o "$INTOVOID" -f +zstd -d tmp1.zst tmp2.zst -o tmp touch tmpexists -$ZSTD tmp1 tmp2 -f -o tmpexists -$ZSTD tmp1 tmp2 -o tmpexists && die "should have refused to overwrite" +zstd tmp1 tmp2 -f -o tmpexists +zstd tmp1 tmp2 -o tmpexists && die "should have refused to overwrite" # Bug: PR #972 if [ "$?" -eq 139 ]; then die "should not have segfaulted" fi println "\n===> multiple files and shell completion " -$DATAGEN -s1 > tmp1 2> $INTOVOID -$DATAGEN -s2 -g100K > tmp2 2> $INTOVOID -$DATAGEN -s3 -g1M > tmp3 2> $INTOVOID +datagen -s1 > tmp1 2> $INTOVOID +datagen -s2 -g100K > tmp2 2> $INTOVOID +datagen -s3 -g1M > tmp3 2> $INTOVOID println "compress tmp* : " -$ZSTD -f tmp* +zstd -f tmp* test -f tmp1.zst test -f tmp2.zst test -f tmp3.zst rm tmp1 tmp2 tmp3 println "decompress tmp* : " -$ZSTD -df ./*.zst +zstd -df ./*.zst test -f tmp1 test -f tmp2 test -f tmp3 println "compress tmp* into stdout > tmpall : " -$ZSTD -c tmp1 tmp2 tmp3 > tmpall +zstd -c tmp1 tmp2 tmp3 > tmpall test -f tmpall # should check size of tmpall (should be tmp1.zst + tmp2.zst + tmp3.zst) println "decompress tmpall* into stdout > tmpdec : " cp tmpall tmpall2 -$ZSTD -dc tmpall* > tmpdec +zstd -dc tmpall* > tmpdec test -f tmpdec # should check size of tmpdec (should be 2*(tmp1 + tmp2 + tmp3)) println "compress multiple files including a missing one (notHere) : " -$ZSTD -f tmp1 notHere tmp2 && die "missing file not detected!" +zstd -f tmp1 notHere tmp2 && die "missing file not detected!" rm tmp* @@ -364,8 +381,8 @@ if [ "$isWindows" = false ] ; then mkfifo tmp_named_pipe # note : fifo test doesn't work in combination with `dd` or `cat` echo "Hello World!" > tmp_named_pipe & - $ZSTD tmp_named_pipe -o tmp_compressed - $ZSTD -d -o tmp_decompressed tmp_compressed + zstd tmp_named_pipe -o tmp_compressed + zstd -d -o tmp_decompressed tmp_compressed $DIFF -s tmp_original tmp_decompressed rm -rf tmp* fi @@ -375,12 +392,12 @@ if [ -n "$DEVNULLRIGHTS" ] ; then # these tests requires sudo rights, which is uncommon. # they are only triggered if DEVNULLRIGHTS macro is defined. println "\n===> checking /dev/null permissions are unaltered " - $DATAGEN > tmp - sudo $ZSTD tmp -o $INTOVOID # sudo rights could modify /dev/null permissions - sudo $ZSTD tmp -c > $INTOVOID - $ZSTD tmp -f -o tmp.zst - sudo $ZSTD -d tmp.zst -c > $INTOVOID - sudo $ZSTD -d tmp.zst -o $INTOVOID + datagen > tmp + sudoZstd tmp -o $INTOVOID # sudo rights could modify /dev/null permissions + sudoZstd tmp -c > $INTOVOID + zstd tmp -f -o tmp.zst + sudoZstd -d tmp.zst -c > $INTOVOID + sudoZstd -d tmp.zst -o $INTOVOID ls -las $INTOVOID | grep "rw-rw-rw-" fi @@ -394,16 +411,16 @@ mkdir tmpInputTestDir/we/must/go mkdir tmpInputTestDir/we/must/go/deeper println cool > tmpInputTestDir/we/must/go/deeper/tmp2 mkdir tmpOutDir -$ZSTD tmp1 tmpInputTestDir/we/must/go/deeper/tmp2 --output-dir-flat tmpOutDir +zstd tmp1 tmpInputTestDir/we/must/go/deeper/tmp2 --output-dir-flat tmpOutDir test -f tmpOutDir/tmp1.zst test -f tmpOutDir/tmp2.zst println "test : decompress multiple files into an output directory, --output-dir-flat" mkdir tmpOutDirDecomp -$ZSTD tmpOutDir -r -d --output-dir-flat tmpOutDirDecomp +zstd tmpOutDir -r -d --output-dir-flat tmpOutDirDecomp test -f tmpOutDirDecomp/tmp2 test -f tmpOutDirDecomp/tmp1 rm -f tmpOutDirDecomp/* -$ZSTD tmpOutDir -r -d --output-dir-flat=tmpOutDirDecomp +zstd tmpOutDir -r -d --output-dir-flat=tmpOutDirDecomp test -f tmpOutDirDecomp/tmp2 test -f tmpOutDirDecomp/tmp1 rm -rf tmp* @@ -414,14 +431,14 @@ println "Hello world!, file1" > tmp1 println "Hello world!, file2" > tmp2 println tmp1 > tmp_fileList println tmp2 >> tmp_fileList -$ZSTD -f --filelist=tmp_fileList +zstd -f --filelist=tmp_fileList test -f tmp2.zst test -f tmp1.zst println "test : reading file list from a symlink, --filelist=FILE" rm -f *.zst ln -s tmp_fileList tmp_symLink -$ZSTD -f --filelist=tmp_symLink +zstd -f --filelist=tmp_symLink test -f tmp2.zst test -f tmp1.zst @@ -431,7 +448,7 @@ println "Hello world!, file3" > tmp3 println "Hello world!, file4" > tmp4 println tmp3 > tmp_fileList2 println tmp4 >> tmp_fileList2 -$ZSTD -f --filelist=tmp_fileList --filelist=tmp_fileList2 +zstd -f --filelist=tmp_fileList --filelist=tmp_fileList2 test -f tmp1.zst test -f tmp2.zst test -f tmp3.zst @@ -441,7 +458,7 @@ println "test : decompress multiple files reading them from a file, --filelist=F rm -f tmp1 tmp2 println tmp1.zst > tmpZst println tmp2.zst >> tmpZst -$ZSTD -d -f --filelist=tmpZst +zstd -d -f --filelist=tmpZst test -f tmp1 test -f tmp2 @@ -449,57 +466,57 @@ println "test : decompress multiple files reading them from multiple files, --fi rm -f tmp1 tmp2 tmp3 tmp4 println tmp3.zst > tmpZst2 println tmp4.zst >> tmpZst2 -$ZSTD -d -f --filelist=tmpZst --filelist=tmpZst2 +zstd -d -f --filelist=tmpZst --filelist=tmpZst2 test -f tmp1 test -f tmp2 test -f tmp3 test -f tmp4 println "test : survive a list of files which is text garbage (--filelist=FILE)" -$DATAGEN > tmp_badList -$ZSTD -f --filelist=tmp_badList && die "should have failed : list is text garbage" +datagen > tmp_badList +zstd -f --filelist=tmp_badList && die "should have failed : list is text garbage" println "test : survive a list of files which is binary garbage (--filelist=FILE)" -$DATAGEN -P0 -g1M > tmp_badList -$ZSTD -qq -f --filelist=tmp_badList && die "should have failed : list is binary garbage" # let's avoid printing binary garbage on console +datagen -P0 -g1M > tmp_badList +zstd -qq -f --filelist=tmp_badList && die "should have failed : list is binary garbage" # let's avoid printing binary garbage on console println "test : try to overflow internal list of files (--filelist=FILE)" touch tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 ls tmp* > tmpList -$ZSTD -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3 # can trigger an overflow of internal file list +zstd -f tmp1 --filelist=tmpList --filelist=tmpList tmp2 tmp3 # can trigger an overflow of internal file list rm -rf tmp* println "\n===> --[no-]content-size tests" -$DATAGEN > tmp_contentsize -$ZSTD -f tmp_contentsize -$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" -$ZSTD -f --no-content-size tmp_contentsize -$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" && die -$ZSTD -f --content-size tmp_contentsize -$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" -$ZSTD -f --content-size --no-content-size tmp_contentsize -$ZSTD -lv tmp_contentsize.zst | grep "Decompressed Size:" && die +datagen > tmp_contentsize +zstd -f tmp_contentsize +zstd -lv tmp_contentsize.zst | grep "Decompressed Size:" +zstd -f --no-content-size tmp_contentsize +zstd -lv tmp_contentsize.zst | grep "Decompressed Size:" && die +zstd -f --content-size tmp_contentsize +zstd -lv tmp_contentsize.zst | grep "Decompressed Size:" +zstd -f --content-size --no-content-size tmp_contentsize +zstd -lv tmp_contentsize.zst | grep "Decompressed Size:" && die rm -rf tmp* println "test : show-default-cparams regular" -$DATAGEN > tmp -$ZSTD --show-default-cparams -f tmp +datagen > tmp +zstd --show-default-cparams -f tmp rm -rf tmp* println "test : show-default-cparams recursive" mkdir tmp_files -$DATAGEN -g15000 > tmp_files/tmp1 -$DATAGEN -g129000 > tmp_files/tmp2 -$DATAGEN -g257000 > tmp_files/tmp3 -$ZSTD --show-default-cparams -f -r tmp_files +datagen -g15000 > tmp_files/tmp1 +datagen -g129000 > tmp_files/tmp2 +datagen -g257000 > tmp_files/tmp3 +zstd --show-default-cparams -f -r tmp_files rm -rf tmp* println "\n===> Advanced compression parameters " -println "Hello world!" | $ZSTD --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!" -println "Hello world!" | $ZSTD --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!" -println "Hello world!" | $ZSTD --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!" -println "Hello world!" | $ZSTD --zstd=strategy=10 - -o tmp.zst && die "parameter out of bound not detected!" # > btultra2 : does not exist +println "Hello world!" | zstd --zstd=windowLog=21, - -o tmp.zst && die "wrong parameters not detected!" +println "Hello world!" | zstd --zstd=windowLo=21 - -o tmp.zst && die "wrong parameters not detected!" +println "Hello world!" | zstd --zstd=windowLog=21,slog - -o tmp.zst && die "wrong parameters not detected!" +println "Hello world!" | zstd --zstd=strategy=10 - -o tmp.zst && die "parameter out of bound not detected!" # > btultra2 : does not exist test ! -f tmp.zst # tmp.zst should not be created roundTripTest -g512K roundTripTest -g512K " --zstd=mml=3,tlen=48,strat=6" @@ -511,42 +528,42 @@ roundTripTest -g64K "19 --zstd=strat=9" # btultra2 println "\n===> Pass-Through mode " -println "Hello world 1!" | $ZSTD -df -println "Hello world 2!" | $ZSTD -dcf +println "Hello world 1!" | zstd -df +println "Hello world 2!" | zstd -dcf println "Hello world 3!" > tmp1 -$ZSTD -dcf tmp1 +zstd -dcf tmp1 println "\n===> frame concatenation " println "hello " > hello.tmp println "world!" > world.tmp cat hello.tmp world.tmp > helloworld.tmp -$ZSTD -c hello.tmp > hello.zstd -$ZSTD -c world.tmp > world.zstd -cat hello.zstd world.zstd > helloworld.zstd -$ZSTD -dc helloworld.zstd > result.tmp +zstd -c hello.tmp > hello.zst +zstd -c world.tmp > world.zst +cat hello.zst world.zst > helloworld.zst +zstd -dc helloworld.zst > result.tmp cat result.tmp $DIFF helloworld.tmp result.tmp println "frame concatenation without checksum" -$ZSTD -c hello.tmp > hello.zstd --no-check -$ZSTD -c world.tmp > world.zstd --no-check -cat hello.zstd world.zstd > helloworld.zstd -$ZSTD -dc helloworld.zstd > result.tmp +zstd -c hello.tmp > hello.zst --no-check +zstd -c world.tmp > world.zst --no-check +cat hello.zst world.zst > helloworld.zstd +zstd -dc helloworld.zst > result.tmp $DIFF helloworld.tmp result.tmp println "testing zstdcat symlink" -ln -sf $ZSTD_BIN zstdcat -$EXE_PREFIX ./zstdcat helloworld.zstd > result.tmp +ln -sf "$ZSTD_BIN" zstdcat +$EXE_PREFIX ./zstdcat helloworld.zst > result.tmp $DIFF helloworld.tmp result.tmp -ln -s helloworld.zstd helloworld.link.zstd -$EXE_PREFIX ./zstdcat helloworld.link.zstd > result.tmp +ln -s helloworld.zst helloworld.link.zst +$EXE_PREFIX ./zstdcat helloworld.link.zst > result.tmp $DIFF helloworld.tmp result.tmp rm zstdcat rm result.tmp println "testing zcat symlink" -ln -sf $ZSTD_BIN zcat -$EXE_PREFIX ./zcat helloworld.zstd > result.tmp +ln -sf "$ZSTD_BIN" zcat +$EXE_PREFIX ./zcat helloworld.zst > result.tmp $DIFF helloworld.tmp result.tmp -$EXE_PREFIX ./zcat helloworld.link.zstd > result.tmp +$EXE_PREFIX ./zcat helloworld.link.zst > result.tmp $DIFF helloworld.tmp result.tmp rm zcat rm ./*.tmp ./*.zstd @@ -556,10 +573,10 @@ println "frame concatenation tests completed" if [ "$isWindows" = false ] && [ "$UNAME" != 'SunOS' ] && [ "$UNAME" != "OpenBSD" ] ; then println "\n**** flush write error test **** " -println "println foo | $ZSTD > /dev/full" -println foo | $ZSTD > /dev/full && die "write error not detected!" -println "println foo | $ZSTD | $ZSTD -d > /dev/full" -println foo | $ZSTD | $ZSTD -d > /dev/full && die "write error not detected!" +println "println foo | zstd > /dev/full" +println foo | zstd > /dev/full && die "write error not detected!" +println "println foo | zstd | zstd -d > /dev/full" +println foo | zstd | zstd -d > /dev/full && die "write error not detected!" fi @@ -572,15 +589,15 @@ rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst println "hello world" > hello.tmp ln -s hello.tmp world.tmp ln -s hello.tmp world2.tmp -$ZSTD world.tmp hello.tmp || true +zstd world.tmp hello.tmp || true test -f hello.tmp.zst # regular file should have been compressed! test ! -f world.tmp.zst # symbolic link should not have been compressed! -$ZSTD world.tmp || true +zstd world.tmp || true test ! -f world.tmp.zst # symbolic link should not have been compressed! -$ZSTD world.tmp world2.tmp || true +zstd world.tmp world2.tmp || true test ! -f world.tmp.zst # symbolic link should not have been compressed! test ! -f world2.tmp.zst # symbolic link should not have been compressed! -$ZSTD world.tmp hello.tmp -f +zstd world.tmp hello.tmp -f test -f world.tmp.zst # symbolic link should have been compressed with --force rm -f hello.tmp world.tmp world2.tmp hello.tmp.zst world.tmp.zst @@ -589,26 +606,26 @@ fi println "\n===> test sparse file support " -$DATAGEN -g5M -P100 > tmpSparse -$ZSTD tmpSparse -c | $ZSTD -dv -o tmpSparseRegen +datagen -g5M -P100 > tmpSparse +zstd tmpSparse -c | zstd -dv -o tmpSparseRegen $DIFF -s tmpSparse tmpSparseRegen -$ZSTD tmpSparse -c | $ZSTD -dv --sparse -c > tmpOutSparse +zstd tmpSparse -c | zstd -dv --sparse -c > tmpOutSparse $DIFF -s tmpSparse tmpOutSparse -$ZSTD tmpSparse -c | $ZSTD -dv --no-sparse -c > tmpOutNoSparse +zstd tmpSparse -c | zstd -dv --no-sparse -c > tmpOutNoSparse $DIFF -s tmpSparse tmpOutNoSparse ls -ls tmpSparse* # look at file size and block size on disk -$DATAGEN -s1 -g1200007 -P100 | $ZSTD | $ZSTD -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks) -$DATAGEN -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd +datagen -s1 -g1200007 -P100 | zstd | zstd -dv --sparse -c > tmpSparseOdd # Odd size file (to not finish on an exact nb of blocks) +datagen -s1 -g1200007 -P100 | $DIFF -s - tmpSparseOdd ls -ls tmpSparseOdd # look at file size and block size on disk println "\n Sparse Compatibility with Console :" -println "Hello World 1 !" | $ZSTD | $ZSTD -d -c -println "Hello World 2 !" | $ZSTD | $ZSTD -d | cat +println "Hello World 1 !" | zstd | zstd -d -c +println "Hello World 2 !" | zstd | zstd -d | cat println "\n Sparse Compatibility with Append :" -$DATAGEN -P100 -g1M > tmpSparse1M +datagen -P100 -g1M > tmpSparse1M cat tmpSparse1M tmpSparse1M > tmpSparse2M -$ZSTD -v -f tmpSparse1M -o tmpSparseCompressed -$ZSTD -d -v -f tmpSparseCompressed -o tmpSparseRegenerated -$ZSTD -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated +zstd -v -f tmpSparse1M -o tmpSparseCompressed +zstd -d -v -f tmpSparseCompressed -o tmpSparseRegenerated +zstd -d -v -f tmpSparseCompressed -c >> tmpSparseRegenerated ls -ls tmpSparse* # look at file size and block size on disk $DIFF tmpSparse2M tmpSparseRegenerated rm tmpSparse* @@ -616,25 +633,25 @@ rm tmpSparse* println "\n===> stream-size mode" -$DATAGEN -g11000 > tmp +datagen -g11000 > tmp println "test : basic file compression vs sized streaming compression" -file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst) -stream_size=$(cat tmp | $ZSTD -14 --stream-size=11000 | wc -c) +file_size=$(zstd -14 -f tmp -o tmp.zst && wc -c < tmp.zst) +stream_size=$(cat tmp | zstd -14 --stream-size=11000 | wc -c) if [ "$stream_size" -gt "$file_size" ]; then die "hinted compression larger than expected" fi println "test : sized streaming compression and decompression" -cat tmp | $ZSTD -14 -f tmp -o --stream-size=11000 tmp.zst -$ZSTD -df tmp.zst -o tmp_decompress +cat tmp | zstd -14 -f tmp -o --stream-size=11000 tmp.zst +zstd -df tmp.zst -o tmp_decompress cmp tmp tmp_decompress || die "difference between original and decompressed file" println "test : incorrect stream size" -cat tmp | $ZSTD -14 -f -o tmp.zst --stream-size=11001 && die "should fail with incorrect stream size" +cat tmp | zstd -14 -f -o tmp.zst --stream-size=11001 && die "should fail with incorrect stream size" println "\n===> zstd zero weight dict test " rm -f tmp* cp "$TESTDIR/dict-files/zero-weight-dict" tmp_input -$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input -$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp +zstd -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input +zstd -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp $DIFF tmp_decomp tmp_input rm -rf tmp* @@ -642,87 +659,87 @@ println "\n===> zstd (valid) zero weight dict test " rm -f tmp* # 0 has a non-zero weight in the dictionary echo "0000000000000000000000000" > tmp_input -$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input -$ZSTD -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp +zstd -D "$TESTDIR/dict-files/zero-weight-dict" tmp_input +zstd -D "$TESTDIR/dict-files/zero-weight-dict" -d tmp_input.zst -o tmp_decomp $DIFF tmp_decomp tmp_input rm -rf tmp* println "\n===> size-hint mode" -$DATAGEN -g11000 > tmp -$DATAGEN -g11000 > tmp2 -$DATAGEN > tmpDict +datagen -g11000 > tmp +datagen -g11000 > tmp2 +datagen > tmpDict println "test : basic file compression vs hinted streaming compression" -file_size=$($ZSTD -14 -f tmp -o tmp.zst && wc -c < tmp.zst) -stream_size=$(cat tmp | $ZSTD -14 --size-hint=11000 | wc -c) +file_size=$(zstd -14 -f tmp -o tmp.zst && wc -c < tmp.zst) +stream_size=$(cat tmp | zstd -14 --size-hint=11000 | wc -c) if [ "$stream_size" -ge "$file_size" ]; then die "hinted compression larger than expected" fi println "test : hinted streaming compression and decompression" -cat tmp | $ZSTD -14 -f -o tmp.zst --size-hint=11000 -$ZSTD -df tmp.zst -o tmp_decompress +cat tmp | zstd -14 -f -o tmp.zst --size-hint=11000 +zstd -df tmp.zst -o tmp_decompress cmp tmp tmp_decompress || die "difference between original and decompressed file" println "test : hinted streaming compression with dictionary" -cat tmp | $ZSTD -14 -f -D tmpDict --size-hint=11000 | $ZSTD -t -D tmpDict +cat tmp | zstd -14 -f -D tmpDict --size-hint=11000 | zstd -t -D tmpDict println "test : multiple file compression with hints and dictionary" -$ZSTD -14 -f -D tmpDict --size-hint=11000 tmp tmp2 -$ZSTD -14 -f -o tmp1_.zst -D tmpDict --size-hint=11000 tmp -$ZSTD -14 -f -o tmp2_.zst -D tmpDict --size-hint=11000 tmp2 +zstd -14 -f -D tmpDict --size-hint=11000 tmp tmp2 +zstd -14 -f -o tmp1_.zst -D tmpDict --size-hint=11000 tmp +zstd -14 -f -o tmp2_.zst -D tmpDict --size-hint=11000 tmp2 cmp tmp.zst tmp1_.zst || die "first file's output differs" cmp tmp2.zst tmp2_.zst || die "second file's output differs" println "test : incorrect hinted stream sizes" -cat tmp | $ZSTD -14 -f --size-hint=11050 | $ZSTD -t # slightly too high -cat tmp | $ZSTD -14 -f --size-hint=10950 | $ZSTD -t # slightly too low -cat tmp | $ZSTD -14 -f --size-hint=22000 | $ZSTD -t # considerably too high -cat tmp | $ZSTD -14 -f --size-hint=5500 | $ZSTD -t # considerably too low +cat tmp | zstd -14 -f --size-hint=11050 | zstd -t # slightly too high +cat tmp | zstd -14 -f --size-hint=10950 | zstd -t # slightly too low +cat tmp | zstd -14 -f --size-hint=22000 | zstd -t # considerably too high +cat tmp | zstd -14 -f --size-hint=5500 | zstd -t # considerably too low println "\n===> dictionary tests " println "- test with raw dict (content only) " -$DATAGEN > tmpDict -$DATAGEN -g1M | $MD5SUM > tmp1 -$DATAGEN -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | $MD5SUM > tmp2 +datagen > tmpDict +datagen -g1M | $MD5SUM > tmp1 +datagen -g1M | zstd -D tmpDict | zstd -D tmpDict -dvq | $MD5SUM > tmp2 $DIFF -q tmp1 tmp2 println "- Create first dictionary " TESTFILE="$PRGDIR"/zstdcli.c -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp println "- Test dictionary compression with tmpDict as an input file and dictionary" -$ZSTD -f tmpDict -D tmpDict && die "compression error not detected!" +zstd -f tmpDict -D tmpDict && die "compression error not detected!" println "- Dictionary compression roundtrip" -$ZSTD -f tmp -D tmpDict -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result println "- Dictionary compression with btlazy2 strategy" -$ZSTD -f tmp -D tmpDict --zstd=strategy=6 -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict --zstd=strategy=6 +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result if [ -n "$hasMT" ] then println "- Test dictionary compression with multithreading " - $DATAGEN -g5M | $ZSTD -T2 -D tmpDict | $ZSTD -t -D tmpDict # fails with v1.3.2 + datagen -g5M | zstd -T2 -D tmpDict | zstd -t -D tmpDict # fails with v1.3.2 fi println "- Create second (different) dictionary " -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC -$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC +zstd -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" println "- Create dictionary with short dictID" -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 cmp tmpDict tmpDict1 && die "dictionaries should have different ID !" println "- Create dictionary with wrong dictID parameter order (must fail)" -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument " +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID -o 1 tmpDict1 && die "wrong order : --dictID must be followed by argument " println "- Create dictionary with size limit" -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K -v +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K -v println "- Create dictionary with small size limit" -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict=1K -v +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict=1K -v println "- Create dictionary with wrong parameter order (must fail)" -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument " +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict3 --maxdict -v 4K && die "wrong order : --maxdict must be followed by argument " println "- Compress without dictID" -$ZSTD -f tmp -D tmpDict1 --no-dictID -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict1 --no-dictID +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result println "- Compress with wrong argument order (must fail)" -$ZSTD tmp -Df tmpDict1 -c > $INTOVOID && die "-D must be followed by dictionary name " +zstd tmp -Df tmpDict1 -c > $INTOVOID && die "-D must be followed by dictionary name " println "- Compress multiple files with dictionary" rm -rf dirTestDict mkdir dirTestDict @@ -730,8 +747,8 @@ cp "$TESTDIR"/*.c dirTestDict cp "$PRGDIR"/*.c dirTestDict cp "$PRGDIR"/*.h dirTestDict $MD5SUM dirTestDict/* > tmph1 -$ZSTD -f --rm dirTestDict/* -D tmpDictC -$ZSTD -d --rm dirTestDict/*.zst -D tmpDictC # note : use internal checksum by default +zstd -f --rm dirTestDict/* -D tmpDictC +zstd -d --rm dirTestDict/*.zst -D tmpDictC # note : use internal checksum by default case "$UNAME" in Darwin) println "md5sum -c not supported on OS-X : test skipped" ;; # not compatible with OS-X's md5 *) $MD5SUM -c tmph1 ;; @@ -739,65 +756,65 @@ esac rm -rf dirTestDict println "- dictionary builder on bogus input" println "Hello World" > tmp -$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : not enough input source" -$DATAGEN -P0 -g10M > tmp -$ZSTD --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise" +zstd --train-legacy -q tmp && die "Dictionary training should fail : not enough input source" +datagen -P0 -g10M > tmp +zstd --train-legacy -q tmp && die "Dictionary training should fail : source is pure noise" println "- Test -o before --train" rm -f tmpDict dictionary -$ZSTD -o tmpDict --train "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd -o tmpDict --train "$TESTDIR"/*.c "$PRGDIR"/*.c test -f tmpDict -$ZSTD --train "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train "$TESTDIR"/*.c "$PRGDIR"/*.c test -f dictionary println "- Test dictionary training fails" echo "000000000000000000000000000000000" > tmpz -$ZSTD --train tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros" +zstd --train tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros" if [ -n "$hasMT" ] then - $ZSTD --train -T0 tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros" + zstd --train -T0 tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz tmpz && die "Dictionary training should fail : source is all zeros" println "- Create dictionary with multithreading enabled" - $ZSTD --train -T0 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict + zstd --train -T0 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict fi rm tmp* dictionary println "\n===> fastCover dictionary builder : advanced options " TESTFILE="$PRGDIR"/zstdcli.c -$DATAGEN > tmpDict +datagen > tmpDict println "- Create first dictionary" -$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict +zstd --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp -$ZSTD -f tmp -D tmpDict -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result println "- Create second (different) dictionary" -$ZSTD --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC -$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" -$ZSTD --train-fastcover=k=56,d=8 && die "Create dictionary without input file" +zstd --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC +zstd -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" +zstd --train-fastcover=k=56,d=8 && die "Create dictionary without input file" println "- Create dictionary with short dictID" -$ZSTD --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 +zstd --train-fastcover=k=46,d=8,f=15,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 cmp tmpDict tmpDict1 && die "dictionaries should have different ID !" println "- Create dictionaries with shrink-dict flag enabled" -$ZSTD --train-fastcover=steps=1,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict -$ZSTD --train-fastcover=steps=1,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict1 -$ZSTD --train-fastcover=steps=1,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict2 +zstd --train-fastcover=steps=1,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict +zstd --train-fastcover=steps=1,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict1 +zstd --train-fastcover=steps=1,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpShrinkDict2 println "- Create dictionary with size limit" -$ZSTD --train-fastcover=steps=1 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K +zstd --train-fastcover=steps=1 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K println "- Create dictionary using all samples for both training and testing" -$ZSTD --train-fastcover=k=56,d=8,split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover=k=56,d=8,split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Create dictionary using f=16" -$ZSTD --train-fastcover=k=56,d=8,f=16 -r "$TESTDIR"/*.c "$PRGDIR"/*.c -$ZSTD --train-fastcover=k=56,d=8,accel=15 -r "$TESTDIR"/*.c "$PRGDIR"/*.c && die "Created dictionary using accel=15" +zstd --train-fastcover=k=56,d=8,f=16 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover=k=56,d=8,accel=15 -r "$TESTDIR"/*.c "$PRGDIR"/*.c && die "Created dictionary using accel=15" println "- Create dictionary using accel=2" -$ZSTD --train-fastcover=k=56,d=8,accel=2 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover=k=56,d=8,accel=2 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Create dictionary using accel=10" -$ZSTD --train-fastcover=k=56,d=8,accel=10 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover=k=56,d=8,accel=10 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Create dictionary with multithreading" -$ZSTD --train-fastcover -T4 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover -T4 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Test -o before --train-fastcover" rm -f tmpDict dictionary -$ZSTD -o tmpDict --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd -o tmpDict --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c test -f tmpDict -$ZSTD --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-fastcover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c test -f dictionary rm tmp* dictionary @@ -805,27 +822,27 @@ rm tmp* dictionary println "\n===> legacy dictionary builder " TESTFILE="$PRGDIR"/zstdcli.c -$DATAGEN > tmpDict +datagen > tmpDict println "- Create first dictionary" -$ZSTD --train-legacy=selectivity=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict +zstd --train-legacy=selectivity=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp -$ZSTD -f tmp -D tmpDict -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result -$ZSTD --train-legacy=s=8 && die "Create dictionary without input files (should error)" +zstd --train-legacy=s=8 && die "Create dictionary without input files (should error)" println "- Create second (different) dictionary" -$ZSTD --train-legacy=s=5 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC -$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" +zstd --train-legacy=s=5 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC +zstd -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" println "- Create dictionary with short dictID" -$ZSTD --train-legacy -s5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 +zstd --train-legacy -s5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 cmp tmpDict tmpDict1 && die "dictionaries should have different ID !" println "- Create dictionary with size limit" -$ZSTD --train-legacy -s9 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K +zstd --train-legacy -s9 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K println "- Test -o before --train-legacy" rm -f tmpDict dictionary -$ZSTD -o tmpDict --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd -o tmpDict --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c test -f tmpDict -$ZSTD --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-legacy "$TESTDIR"/*.c "$PRGDIR"/*.c test -f dictionary rm tmp* dictionary @@ -833,71 +850,71 @@ rm tmp* dictionary println "\n===> integrity tests " println "test one file (tmp1.zst) " -$DATAGEN > tmp1 -$ZSTD tmp1 -$ZSTD -t tmp1.zst -$ZSTD --test tmp1.zst +datagen > tmp1 +zstd tmp1 +zstd -t tmp1.zst +zstd --test tmp1.zst println "test multiple files (*.zst) " -$ZSTD -t ./*.zst +zstd -t ./*.zst println "test bad files (*) " -$ZSTD -t ./* && die "bad files not detected !" -$ZSTD -t tmp1 && die "bad file not detected !" +zstd -t ./* && die "bad files not detected !" +zstd -t tmp1 && die "bad file not detected !" cp tmp1 tmp2.zst -$ZSTD -t tmp2.zst && die "bad file not detected !" -$DATAGEN -g0 > tmp3 -$ZSTD -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad +zstd -t tmp2.zst && die "bad file not detected !" +datagen -g0 > tmp3 +zstd -t tmp3 && die "bad file not detected !" # detects 0-sized files as bad println "test --rm and --test combined " -$ZSTD -t --rm tmp1.zst +zstd -t --rm tmp1.zst test -f tmp1.zst # check file is still present split -b16384 tmp1.zst tmpSplit. -$ZSTD -t tmpSplit.* && die "bad file not detected !" -$DATAGEN | $ZSTD -c | $ZSTD -t +zstd -t tmpSplit.* && die "bad file not detected !" +datagen | zstd -c | zstd -t println "\n===> golden files tests " -$ZSTD -t -r "$TESTDIR/golden-compression" -$ZSTD -c -r "$TESTDIR/golden-compression" | $ZSTD -t +zstd -t -r "$TESTDIR/golden-compression" +zstd -c -r "$TESTDIR/golden-compression" | zstd -t println "\n===> benchmark mode tests " println "bench one file" -$DATAGEN > tmp1 -$ZSTD -bi0 tmp1 +datagen > tmp1 +zstd -bi0 tmp1 println "bench multiple levels" -$ZSTD -i0b0e3 tmp1 +zstd -i0b0e3 tmp1 println "bench negative level" -$ZSTD -bi0 --fast tmp1 +zstd -bi0 --fast tmp1 println "with recursive and quiet modes" -$ZSTD -rqi0b1e2 tmp1 +zstd -rqi0b1e2 tmp1 println "benchmark decompression only" -$ZSTD -f tmp1 -$ZSTD -b -d -i0 tmp1.zst +zstd -f tmp1 +zstd -b -d -i0 tmp1.zst println "\n===> zstd compatibility tests " -$DATAGEN > tmp +datagen > tmp rm -f tmp.zst -$ZSTD --format=zstd -f tmp +zstd --format=zstd -f tmp test -f tmp.zst println "\n===> gzip compatibility tests " GZIPMODE=1 -$ZSTD --format=gzip -V || GZIPMODE=0 +zstd --format=gzip -V || GZIPMODE=0 if [ $GZIPMODE -eq 1 ]; then println "gzip support detected" GZIPEXE=1 gzip -V || GZIPEXE=0 if [ $GZIPEXE -eq 1 ]; then - $DATAGEN > tmp - $ZSTD --format=gzip -f tmp + datagen > tmp + zstd --format=gzip -f tmp gzip -t -v tmp.gz gzip -f tmp - $ZSTD -d -f -v tmp.gz + zstd -d -f -v tmp.gz rm tmp* else println "gzip binary not detected" @@ -910,50 +927,50 @@ fi println "\n===> gzip frame tests " if [ $GZIPMODE -eq 1 ]; then - $DATAGEN > tmp - $ZSTD -f --format=gzip tmp - $ZSTD -f tmp - cat tmp.gz tmp.zst tmp.gz tmp.zst | $ZSTD -d -f -o tmp - truncateLastByte tmp.gz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !" + datagen > tmp + zstd -f --format=gzip tmp + zstd -f tmp + cat tmp.gz tmp.zst tmp.gz tmp.zst | zstd -d -f -o tmp + truncateLastByte tmp.gz | zstd -t > $INTOVOID && die "incomplete frame not detected !" rm tmp* else println "gzip mode not supported" fi if [ $GZIPMODE -eq 1 ]; then - $DATAGEN > tmp + datagen > tmp rm -f tmp.zst - $ZSTD --format=gzip --format=zstd -f tmp + zstd --format=gzip --format=zstd -f tmp test -f tmp.zst fi println "\n===> xz compatibility tests " LZMAMODE=1 -$ZSTD --format=xz -V || LZMAMODE=0 +zstd --format=xz -V || LZMAMODE=0 if [ $LZMAMODE -eq 1 ]; then println "xz support detected" XZEXE=1 xz -Q -V && lzma -Q -V || XZEXE=0 if [ $XZEXE -eq 1 ]; then println "Testing zstd xz and lzma support" - $DATAGEN > tmp - $ZSTD --format=lzma -f tmp - $ZSTD --format=xz -f tmp + datagen > tmp + zstd --format=lzma -f tmp + zstd --format=xz -f tmp xz -Q -t -v tmp.xz xz -Q -t -v tmp.lzma xz -Q -f -k tmp lzma -Q -f -k --lzma1 tmp - $ZSTD -d -f -v tmp.xz - $ZSTD -d -f -v tmp.lzma + zstd -d -f -v tmp.xz + zstd -d -f -v tmp.lzma rm tmp* println "Creating symlinks" - ln -s $ZSTD ./xz - ln -s $ZSTD ./unxz - ln -s $ZSTD ./lzma - ln -s $ZSTD ./unlzma + ln -s "$ZSTD_BIN" ./xz + ln -s "$ZSTD_BIN" ./unxz + ln -s "$ZSTD_BIN" ./lzma + ln -s "$ZSTD_BIN" ./unlzma println "Testing xz and lzma symlinks" - $DATAGEN > tmp + datagen > tmp ./xz tmp xz -Q -d tmp.xz ./lzma tmp @@ -976,13 +993,13 @@ fi println "\n===> xz frame tests " if [ $LZMAMODE -eq 1 ]; then - $DATAGEN > tmp - $ZSTD -f --format=xz tmp - $ZSTD -f --format=lzma tmp - $ZSTD -f tmp - cat tmp.xz tmp.lzma tmp.zst tmp.lzma tmp.xz tmp.zst | $ZSTD -d -f -o tmp - truncateLastByte tmp.xz | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !" - truncateLastByte tmp.lzma | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !" + datagen > tmp + zstd -f --format=xz tmp + zstd -f --format=lzma tmp + zstd -f tmp + cat tmp.xz tmp.lzma tmp.zst tmp.lzma tmp.xz tmp.zst | zstd -d -f -o tmp + truncateLastByte tmp.xz | zstd -t > $INTOVOID && die "incomplete frame not detected !" + truncateLastByte tmp.lzma | zstd -t > $INTOVOID && die "incomplete frame not detected !" rm tmp* else println "xz mode not supported" @@ -991,17 +1008,17 @@ fi println "\n===> lz4 compatibility tests " LZ4MODE=1 -$ZSTD --format=lz4 -V || LZ4MODE=0 +zstd --format=lz4 -V || LZ4MODE=0 if [ $LZ4MODE -eq 1 ]; then println "lz4 support detected" LZ4EXE=1 lz4 -V || LZ4EXE=0 if [ $LZ4EXE -eq 1 ]; then - $DATAGEN > tmp - $ZSTD --format=lz4 -f tmp + datagen > tmp + zstd --format=lz4 -f tmp lz4 -t -v tmp.lz4 lz4 -f tmp - $ZSTD -d -f -v tmp.lz4 + zstd -d -f -v tmp.lz4 rm tmp* else println "lz4 binary not detected" @@ -1013,11 +1030,11 @@ fi if [ $LZ4MODE -eq 1 ]; then println "\n===> lz4 frame tests " - $DATAGEN > tmp - $ZSTD -f --format=lz4 tmp - $ZSTD -f tmp - cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | $ZSTD -d -f -o tmp - truncateLastByte tmp.lz4 | $ZSTD -t > $INTOVOID && die "incomplete frame not detected !" + datagen > tmp + zstd -f --format=lz4 tmp + zstd -f tmp + cat tmp.lz4 tmp.zst tmp.lz4 tmp.zst | zstd -d -f -o tmp + truncateLastByte tmp.lz4 | zstd -t > $INTOVOID && die "incomplete frame not detected !" rm tmp* else println "\nlz4 mode not supported" @@ -1026,7 +1043,7 @@ fi println "\n===> suffix list test" -! $ZSTD -d tmp.abc 2> tmplg +! zstd -d tmp.abc 2> tmplg if [ $GZIPMODE -ne 1 ]; then grep ".gz" tmplg > $INTOVOID && die "Unsupported suffix listed" @@ -1046,39 +1063,39 @@ println "\n===> tar extension tests " rm -f tmp tmp.tar tmp.tzst tmp.tgz tmp.txz tmp.tlz4 -$DATAGEN > tmp +datagen > tmp tar cf tmp.tar tmp -$ZSTD tmp.tar -o tmp.tzst +zstd tmp.tar -o tmp.tzst rm tmp.tar -$ZSTD -d tmp.tzst +zstd -d tmp.tzst [ -e tmp.tar ] || die ".tzst failed to decompress to .tar!" rm -f tmp.tar tmp.tzst if [ $GZIPMODE -eq 1 ]; then tar czf tmp.tgz tmp - $ZSTD -d tmp.tgz + zstd -d tmp.tgz [ -e tmp.tar ] || die ".tgz failed to decompress to .tar!" rm -f tmp.tar tmp.tgz fi if [ $LZMAMODE -eq 1 ]; then - tar c tmp | $ZSTD --format=xz > tmp.txz - $ZSTD -d tmp.txz + tar c tmp | zstd --format=xz > tmp.txz + zstd -d tmp.txz [ -e tmp.tar ] || die ".txz failed to decompress to .tar!" rm -f tmp.tar tmp.txz fi if [ $LZ4MODE -eq 1 ]; then - tar c tmp | $ZSTD --format=lz4 > tmp.tlz4 - $ZSTD -d tmp.tlz4 + tar c tmp | zstd --format=lz4 > tmp.tlz4 + zstd -d tmp.tlz4 [ -e tmp.tar ] || die ".tlz4 failed to decompress to .tar!" rm -f tmp.tar tmp.tlz4 fi touch tmp.t tmp.tz tmp.tzs -! $ZSTD -d tmp.t -! $ZSTD -d tmp.tz -! $ZSTD -d tmp.tzs +! zstd -d tmp.t +! zstd -d tmp.tz +! zstd -d tmp.tzs println "\n===> zstd round-trip tests " @@ -1116,10 +1133,10 @@ then roundTripTest -g8M "3 --long=24 -T2" println "\n===> ovLog tests " - $DATAGEN -g2MB > tmp - refSize=$($ZSTD tmp -6 -c --zstd=wlog=18 | wc -c) - ov9Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c) - ov1Size=$($ZSTD tmp -6 -c --zstd=wlog=18,ovlog=1 | wc -c) + datagen -g2MB > tmp + refSize=$(zstd tmp -6 -c --zstd=wlog=18 | wc -c) + ov9Size=$(zstd tmp -6 -c --zstd=wlog=18,ovlog=9 | wc -c) + ov1Size=$(zstd tmp -6 -c --zstd=wlog=18,ovlog=1 | wc -c) if [ "$refSize" -eq "$ov9Size" ]; then echo ov9Size should be different from refSize exit 1 @@ -1140,66 +1157,66 @@ fi rm tmp* println "\n===> zstd --list/-l single frame tests " -$DATAGEN > tmp1 -$DATAGEN > tmp2 -$DATAGEN > tmp3 -$ZSTD tmp* -$ZSTD -l ./*.zst -$ZSTD -lv ./*.zst | grep "Decompressed Size:" # check that decompressed size is present in header -$ZSTD --list ./*.zst -$ZSTD --list -v ./*.zst +datagen > tmp1 +datagen > tmp2 +datagen > tmp3 +zstd tmp* +zstd -l ./*.zst +zstd -lv ./*.zst | grep "Decompressed Size:" # check that decompressed size is present in header +zstd --list ./*.zst +zstd --list -v ./*.zst println "\n===> zstd --list/-l multiple frame tests " cat tmp1.zst tmp2.zst > tmp12.zst cat tmp12.zst tmp3.zst > tmp123.zst -$ZSTD -l ./*.zst -$ZSTD -lv ./*.zst +zstd -l ./*.zst +zstd -lv ./*.zst println "\n===> zstd --list/-l error detection tests " -$ZSTD -l tmp1 tmp1.zst && die "-l must fail on non-zstd file" -$ZSTD --list tmp* && die "-l must fail on non-zstd file" -$ZSTD -lv tmp1* && die "-l must fail on non-zstd file" -$ZSTD --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file" +zstd -l tmp1 tmp1.zst && die "-l must fail on non-zstd file" +zstd --list tmp* && die "-l must fail on non-zstd file" +zstd -lv tmp1* && die "-l must fail on non-zstd file" +zstd --list -v tmp2 tmp12.zst && die "-l must fail on non-zstd file" println "test : detect truncated compressed file " TEST_DATA_FILE=truncatable-input.txt FULL_COMPRESSED_FILE=${TEST_DATA_FILE}.zst TRUNCATED_COMPRESSED_FILE=truncated-input.txt.zst -$DATAGEN -g50000 > $TEST_DATA_FILE -$ZSTD -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE +datagen -g50000 > $TEST_DATA_FILE +zstd -f $TEST_DATA_FILE -o $FULL_COMPRESSED_FILE dd bs=1 count=100 if=$FULL_COMPRESSED_FILE of=$TRUNCATED_COMPRESSED_FILE -$ZSTD --list $TRUNCATED_COMPRESSED_FILE && die "-l must fail on truncated file" +zstd --list $TRUNCATED_COMPRESSED_FILE && die "-l must fail on truncated file" rm $TEST_DATA_FILE rm $FULL_COMPRESSED_FILE rm $TRUNCATED_COMPRESSED_FILE println "\n===> zstd --list/-l errors when presented with stdin / no files" -$ZSTD -l && die "-l must fail on empty list of files" -$ZSTD -l - && die "-l does not work on stdin" -$ZSTD -l < tmp1.zst && die "-l does not work on stdin" -$ZSTD -l - < tmp1.zst && die "-l does not work on stdin" -$ZSTD -l - tmp1.zst && die "-l does not work on stdin" -$ZSTD -l - tmp1.zst < tmp1.zst && die "-l does not work on stdin" -$ZSTD -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty +zstd -l && die "-l must fail on empty list of files" +zstd -l - && die "-l does not work on stdin" +zstd -l < tmp1.zst && die "-l does not work on stdin" +zstd -l - < tmp1.zst && die "-l does not work on stdin" +zstd -l - tmp1.zst && die "-l does not work on stdin" +zstd -l - tmp1.zst < tmp1.zst && die "-l does not work on stdin" +zstd -l tmp1.zst < tmp2.zst # this will check tmp1.zst, but not tmp2.zst, which is not an error : zstd simply doesn't read stdin in this case. It must not error just because stdin is not a tty println "\n===> zstd --list/-l test with null files " -$DATAGEN -g0 > tmp5 -$ZSTD tmp5 -$ZSTD -l tmp5.zst -$ZSTD -l tmp5* && die "-l must fail on non-zstd file" -$ZSTD -lv tmp5.zst | grep "Decompressed Size: 0.00 KB (0 B)" # check that 0 size is present in header -$ZSTD -lv tmp5* && die "-l must fail on non-zstd file" +datagen -g0 > tmp5 +zstd tmp5 +zstd -l tmp5.zst +zstd -l tmp5* && die "-l must fail on non-zstd file" +zstd -lv tmp5.zst | grep "Decompressed Size: 0.00 KB (0 B)" # check that 0 size is present in header +zstd -lv tmp5* && die "-l must fail on non-zstd file" println "\n===> zstd --list/-l test with no content size field " -$DATAGEN -g513K | $ZSTD > tmp6.zst -$ZSTD -l tmp6.zst -$ZSTD -lv tmp6.zst | grep "Decompressed Size:" && die "Field :Decompressed Size: should not be available in this compressed file" +datagen -g513K | zstd > tmp6.zst +zstd -l tmp6.zst +zstd -lv tmp6.zst | grep "Decompressed Size:" && die "Field :Decompressed Size: should not be available in this compressed file" println "\n===> zstd --list/-l test with no checksum " -$ZSTD -f --no-check tmp1 -$ZSTD -l tmp1.zst -$ZSTD -lv tmp1.zst +zstd -f --no-check tmp1 +zstd -l tmp1.zst +zstd -lv tmp1.zst rm tmp* @@ -1231,22 +1248,22 @@ then roundTripTest -g270000000 " --adapt" roundTripTest -g27000000 " --adapt=min=1,max=4" println "===> test: --adapt must fail on incoherent bounds " - $DATAGEN > tmp - $ZSTD -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds" + datagen > tmp + zstd -f -vv --adapt=min=10,max=9 tmp && die "--adapt must fail on incoherent bounds" println "\n===> rsyncable mode " roundTripTest -g10M " --rsyncable" roundTripTest -g10M " --rsyncable -B100K" println "===> test: --rsyncable must fail with --single-thread" - $ZSTD -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread" + zstd -f -vv --rsyncable --single-thread tmp && die "--rsyncable must fail with --single-thread" fi println "\n===> patch-from tests" -$DATAGEN -g1000 -P50 > tmp_dict -$DATAGEN -g1000 -P10 > tmp_patch -$ZSTD --memory=10000 --patch-from=tmp_dict tmp_patch -o tmp_patch_diff -$ZSTD -d --memory=10000 --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon +datagen -g1000 -P50 > tmp_dict +datagen -g1000 -P10 > tmp_patch +zstd --memory=10000 --patch-from=tmp_dict tmp_patch -o tmp_patch_diff +zstd -d --memory=10000 --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon $DIFF -s tmp_patch_recon tmp_patch rm -rf tmp_* @@ -1312,36 +1329,36 @@ fi println "\n===> cover dictionary builder : advanced options " TESTFILE="$PRGDIR"/zstdcli.c -$DATAGEN > tmpDict +datagen > tmpDict println "- Create first dictionary" -$ZSTD --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict +zstd --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict cp "$TESTFILE" tmp -$ZSTD -f tmp -D tmpDict -$ZSTD -d tmp.zst -D tmpDict -fo result +zstd -f tmp -D tmpDict +zstd -d tmp.zst -D tmpDict -fo result $DIFF "$TESTFILE" result -$ZSTD --train-cover=k=56,d=8 && die "Create dictionary without input file (should error)" +zstd --train-cover=k=56,d=8 && die "Create dictionary without input file (should error)" println "- Create second (different) dictionary" -$ZSTD --train-cover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC -$ZSTD -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" +zstd --train-cover=k=56,d=8 "$TESTDIR"/*.c "$PRGDIR"/*.c "$PRGDIR"/*.h -o tmpDictC +zstd -d tmp.zst -D tmpDictC -fo result && die "wrong dictionary not detected!" println "- Create dictionary using shrink-dict flag" -$ZSTD --train-cover=steps=256,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict -$ZSTD --train-cover=steps=256,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict1 -$ZSTD --train-cover=steps=256,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict2 +zstd --train-cover=steps=256,shrink "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict +zstd --train-cover=steps=256,shrink=1 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict1 +zstd --train-cover=steps=256,shrink=5 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpShrinkDict2 println "- Create dictionary with short dictID" -$ZSTD --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 +zstd --train-cover=k=46,d=8,split=80 "$TESTDIR"/*.c "$PRGDIR"/*.c --dictID=1 -o tmpDict1 cmp tmpDict tmpDict1 && die "dictionaries should have different ID !" println "- Create dictionary with size limit" -$ZSTD --train-cover=steps=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K +zstd --train-cover=steps=8 "$TESTDIR"/*.c "$PRGDIR"/*.c -o tmpDict2 --maxdict=4K println "- Compare size of dictionary from 90% training samples with 80% training samples" -$ZSTD --train-cover=split=90 -r "$TESTDIR"/*.c "$PRGDIR"/*.c -$ZSTD --train-cover=split=80 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-cover=split=90 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-cover=split=80 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Create dictionary using all samples for both training and testing" -$ZSTD --train-cover=split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-cover=split=100 -r "$TESTDIR"/*.c "$PRGDIR"/*.c println "- Test -o before --train-cover" rm -f tmpDict dictionary -$ZSTD -o tmpDict --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd -o tmpDict --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c test -f tmpDict -$ZSTD --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c +zstd --train-cover "$TESTDIR"/*.c "$PRGDIR"/*.c test -f dictionary rm -f tmp* dictionary From c7ae28a67dda681b2509aa975ae334b9d0b24460 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 26 Mar 2020 17:04:52 -0700 Subject: [PATCH 250/402] [circleci] Run test-license.py Run it first because it is very fast (~1 second) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1565099b8ed..ca24f41a9e6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,6 +12,7 @@ jobs: - run: name: Test command: | + ./tests/test-license.py cc -v; CFLAGS="-O0 -Werror" make all && make clean make c99build ; make clean make c11build ; make clean From 5b054d9e904a50bf68417b5cb8fc888f2ed0aa24 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Mon, 23 Mar 2020 16:08:52 -0400 Subject: [PATCH 251/402] Add support for running more tests via CTest --- .travis.yml | 2 +- Makefile | 2 +- appveyor.yml | 4 +-- build/cmake/tests/CMakeLists.txt | 50 ++++++++++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 77227c3648f..e4e45560260 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,7 +100,7 @@ matrix: - make clean - make -j check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - - name: cmake build and test check # ~2mn + - name: cmake build and test check # ~6mn script: - make cmakebuild diff --git a/Makefile b/Makefile index 9b19d4d31a8..9300b1545d0 100644 --- a/Makefile +++ b/Makefile @@ -360,7 +360,7 @@ cmakebuild: $(MAKE) -C $(BUILDIR)/cmake/build -j4; $(MAKE) -C $(BUILDIR)/cmake/build install; $(MAKE) -C $(BUILDIR)/cmake/build uninstall; - cd $(BUILDIR)/cmake/build; ctest -V + cd $(BUILDIR)/cmake/build; ctest -V -L Medium c89build: clean $(CC) -v diff --git a/appveyor.yml b/appveyor.yml index 94e56330b4b..aae626d00f0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -249,9 +249,9 @@ C:\cygwin64\bin\bash --login -c " set -e; cd build/cmake; - CFLAGS='-Werror' cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON .; + CFLAGS='-Werror' cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_FUZZER_FLAGS=-T30s .; make -j4; - ctest -V; + ctest -V -L Medium; " ) - if [%HOST%]==[mingw] ( diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt index 10039fb96da..78cf3270773 100644 --- a/build/cmake/tests/CMakeLists.txt +++ b/build/cmake/tests/CMakeLists.txt @@ -32,6 +32,16 @@ project(tests) +# name: Cache variable name. The value is expected to be a semicolon-separated +# list of command line flags +# default_value: Value to initialize the option with. Can be space separated. +function(AddTestFlagsOption name default_value doc) + string(STRIP "${default_value}" default_value) + string(REGEX REPLACE " +" ";" default_value "${default_value}") + set(${name} ${default_value} CACHE STRING "${doc}") + mark_as_advanced(${name}) +endfunction() + set(CMAKE_INCLUDE_CURRENT_DIR TRUE) # Define programs directory, where sources and header files are located @@ -43,18 +53,52 @@ include_directories(${TESTS_DIR} ${PROGRAMS_DIR} ${LIBRARY_DIR} ${LIBRARY_DIR}/c add_executable(datagen ${PROGRAMS_DIR}/datagen.c ${TESTS_DIR}/datagencli.c) target_link_libraries(datagen libzstd_static) +# +# fullbench +# add_executable(fullbench ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${TESTS_DIR}/fullbench.c) target_link_libraries(fullbench libzstd_static) +add_test(NAME fullbench COMMAND fullbench) +# +# fuzzer +# add_executable(fuzzer ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/fuzzer.c) target_link_libraries(fuzzer libzstd_static) +AddTestFlagsOption(ZSTD_FUZZER_FLAGS "$ENV{FUZZERTEST} $ENV{FUZZER_FLAGS}" + "Semicolon-separated list of flags to pass to the fuzzer test (see `fuzzer -h` for usage)") +add_test(NAME fuzzer COMMAND fuzzer ${ZSTD_FUZZER_FLAGS}) +# Disable the timeout since the run time is too long for the default timeout of +# 1500 seconds and varies considerably between low-end and high-end CPUs. +set_tests_properties(fuzzer PROPERTIES TIMEOUT 0) +# +# zstreamtest +# add_executable(zstreamtest ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/seqgen.c ${TESTS_DIR}/zstreamtest.c) target_link_libraries(zstreamtest libzstd_static) +AddTestFlagsOption(ZSTD_ZSTREAM_FLAGS "$ENV{ZSTREAM_TESTTIME} $ENV{FUZZER_FLAGS}" + "Semicolon-separated list of flags to pass to the zstreamtest test (see `zstreamtest -h` for usage)") +add_test(NAME zstreamtest COMMAND zstreamtest ${ZSTD_ZSTREAM_FLAGS}) + +# +# playTests.sh +# +AddTestFlagsOption(ZSTD_PLAYTESTS_FLAGS "--test-large-data" + "Semicolon-separated list of flags to pass to the playTests.sh test") +add_test(NAME playTests COMMAND sh -c "${TESTS_DIR}/playTests.sh" ${ZSTD_PLAYTESTS_FLAGS}) +if (ZSTD_BUILD_PROGRAMS) + set_property(TEST playTests APPEND PROPERTY ENVIRONMENT + "ZSTD_BIN=$" + "DATAGEN_BIN=$" + ) +else() + message(STATUS "Disabling playTests.sh test because ZSTD_BUILD_PROGRAMS is not enabled") + set_tests_properties(playTests PROPERTIES DISABLED YES) +endif() -add_test( - NAME playTests - COMMAND sh -c "ZSTD_BIN='$' DATAGEN_BIN='$' '${TESTS_DIR}/playTests.sh'") +# Label the "Medium" set of tests (see TESTING.md) +set_property(TEST fuzzer zstreamtest playTests APPEND PROPERTY LABELS Medium) if (UNIX) add_executable(paramgrill ${PROGRAMS_DIR}/benchfn.c ${PROGRAMS_DIR}/benchzstd.c ${PROGRAMS_DIR}/datagen.c ${PROGRAMS_DIR}/util.c ${PROGRAMS_DIR}/timefn.c ${TESTS_DIR}/paramgrill.c) From 7202184ee0f6aaf859bb76364e9372453fb53298 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Fri, 3 Apr 2020 11:55:29 +0200 Subject: [PATCH 252/402] Fixes decompressor when using -Wshorten-64-to-32 (#2062) Spotted on iOS when building with `-Wshorten-64-to-32` (since `__builtin_expect` returns a `long`). --- lib/decompress/huf_decompress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 6cf9c4fddd2..a2478b4c78a 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -835,7 +835,7 @@ HUF_decompress4X2_usingDTable_internal_body( HUF_DECODE_SYMBOLX2_0(op2, &bitD2); HUF_DECODE_SYMBOLX2_0(op3, &bitD3); HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - endSignal = LIKELY( + endSignal = (U32)LIKELY( (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished) & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished) & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished) From 7c420344d2ea0d40034e31afad9000d49d6880ba Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Fri, 3 Apr 2020 19:07:46 +0200 Subject: [PATCH 253/402] Single-file decoder script can now (optionally) create an encoder To complement the single-file decoder a new script was added to create an amalgamated single-file of all of the Zstd source, along with examples and (simple) tests. --- Makefile | 3 +- contrib/single_file_decoder/.gitignore | 4 +- contrib/single_file_decoder/README.md | 12 +- .../{build_test.sh => build_decoder_test.sh} | 3 - .../single_file_decoder/build_library_test.sh | 61 + contrib/single_file_decoder/combine.sh | 100 +- .../create_single_file_decoder.sh | 1 - .../create_single_file_library.sh | 14 + .../single_file_decoder/examples/README.md | 4 +- .../single_file_decoder/examples/emscripten.c | 262 +- .../single_file_decoder/examples/roundtrip.c | 83 + contrib/single_file_decoder/examples/simple.c | 2994 +---------------- .../examples/testcard-dxt1.inl | 2731 +++++++++++++++ .../examples/testcard-zstd.inl | 261 ++ contrib/single_file_decoder/zstd-in.c | 74 + contrib/single_file_decoder/zstd.h | 2052 +++++++++++ contrib/single_file_decoder/zstddeclib-in.c | 41 +- lib/compress/fse_compress.c | 2 + lib/compress/huf_compress.c | 2 + lib/compress/zstd_compress.c | 9 +- lib/decompress/zstd_decompress.c | 3 +- 21 files changed, 5390 insertions(+), 3326 deletions(-) rename contrib/single_file_decoder/{build_test.sh => build_decoder_test.sh} (95%) create mode 100755 contrib/single_file_decoder/build_library_test.sh create mode 100755 contrib/single_file_decoder/create_single_file_library.sh create mode 100644 contrib/single_file_decoder/examples/roundtrip.c create mode 100644 contrib/single_file_decoder/examples/testcard-dxt1.inl create mode 100644 contrib/single_file_decoder/examples/testcard-zstd.inl create mode 100644 contrib/single_file_decoder/zstd-in.c create mode 100644 contrib/single_file_decoder/zstd.h diff --git a/Makefile b/Makefile index b1e3728e118..6965fc043b6 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,8 @@ contrib: lib $(MAKE) -C contrib/pzstd all $(MAKE) -C contrib/seekable_format/examples all $(MAKE) -C contrib/largeNbDicts all - cd contrib/single_file_decoder/ ; ./build_test.sh + cd contrib/single_file_decoder/ ; ./build_decoder_test.sh + cd contrib/single_file_decoder/ ; ./build_library_test.sh .PHONY: cleanTabs cleanTabs: diff --git a/contrib/single_file_decoder/.gitignore b/contrib/single_file_decoder/.gitignore index aa062d1e6d4..7084123b5e1 100644 --- a/contrib/single_file_decoder/.gitignore +++ b/contrib/single_file_decoder/.gitignore @@ -1,2 +1,4 @@ zstddeclib.c - +zstdenclib.c +zstd.c +zsdt.h diff --git a/contrib/single_file_decoder/README.md b/contrib/single_file_decoder/README.md index 73b8f76aad8..7692ebbf6a4 100644 --- a/contrib/single_file_decoder/README.md +++ b/contrib/single_file_decoder/README.md @@ -4,15 +4,23 @@ The script `combine.sh` creates an _amalgamated_ source file that can be used wi Create `zstddeclib.c` from the Zstd source using: ``` -cd zstd/contrib/declib +cd zstd/contrib/single_file_decoder ./combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c ``` Then add the resulting file to your project (see the [example files](examples)). `create_single_file_decoder.sh` will run the above script, creating file `zstddeclib.c`. -`build_test.sh` will create the decoder, then compile and test the library. +`build_decoder_test.sh` will create the decoder, then compile and test the library. Why? ---- Because all it now takes to support decompressing Zstd is the addition of a single file, two if using the header, with no configuration or further build steps. The library is small, adding, for example, 26kB to an Emscripten compiled WebAssembly project. Native implementations add a little more, 40-70kB depending on the compiler and platform. + +Optional Full Library +--------------------- + +The same tool can amalgamate the entire Zstd library for ease of adding both compression and decompression to a project. The [roundtrip example](examples/roundtrip.c) uses the original `zstd.h` with the remaining source files combined into `zstd.c` (currently just over 1MB) created from `zstd-in.c`. As with the standalone decoder the most useful compile flags have already been rolled-in and the resulting files can be added to a project as-is. + +`create_single_file_library.sh` will run the script to create `zstd.c`. +`build_library_test.sh` will create the library, then compile and test the result. diff --git a/contrib/single_file_decoder/build_test.sh b/contrib/single_file_decoder/build_decoder_test.sh similarity index 95% rename from contrib/single_file_decoder/build_test.sh rename to contrib/single_file_decoder/build_decoder_test.sh index ae2b3d87c2a..74e3f1c5733 100755 --- a/contrib/single_file_decoder/build_test.sh +++ b/contrib/single_file_decoder/build_decoder_test.sh @@ -1,8 +1,5 @@ #!/bin/sh -# Where to find the sources -ZSTD_SRC_ROOT="../../lib" - # Temporary compiled binary OUT_FILE="tempbin" diff --git a/contrib/single_file_decoder/build_library_test.sh b/contrib/single_file_decoder/build_library_test.sh new file mode 100755 index 00000000000..d1d5dd0eb4f --- /dev/null +++ b/contrib/single_file_decoder/build_library_test.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# Where to find the sources (only used to copy zstd.h) +ZSTD_SRC_ROOT="../../lib" + +# Temporary compiled binary +OUT_FILE="tempbin" + +# Optional temporary compiled WebAssembly +OUT_WASM="temp.wasm" + +# Amalgamate the sources +./create_single_file_library.sh +# Did combining work? +if [ $? -ne 0 ]; then + echo "Single file library creation script: FAILED" + exit 1 +fi +echo "Single file library creation script: PASSED" + +# Copy the header to here (for the tests) +cp "$ZSTD_SRC_ROOT/zstd.h" zstd.h + +# Compile the generated output +cc -Wall -Wextra -Werror -I. -Os -g0 -o $OUT_FILE zstd.c examples/roundtrip.c +# Did compilation work? +if [ $? -ne 0 ]; then + echo "Compiling roundtrip.c: FAILED" + exit 1 +fi +echo "Compiling roundtrip.c: PASSED" + +# Run then delete the compiled output +./$OUT_FILE +retVal=$? +rm -f $OUT_FILE +# Did the test work? +if [ $retVal -ne 0 ]; then + echo "Running roundtrip.c: FAILED" + exit 1 +fi +echo "Running roundtrip.c: PASSED" + +# Is Emscripten available? +which emcc > /dev/null +if [ $? -ne 0 ]; then + echo "(Skipping Emscripten test)" +else + # Compile the the same example as above + CC_FLAGS="-Wall -Wextra -Werror -Os -g0 -flto" + emcc $CC_FLAGS -s WASM=1 -I. -o $OUT_WASM zstd.c examples/roundtrip.c + # Did compilation work? + if [ $? -ne 0 ]; then + echo "Compiling emscripten.c: FAILED" + exit 1 + fi + echo "Compiling emscripten.c: PASSED" + rm -f $OUT_WASM +fi + +exit 0 diff --git a/contrib/single_file_decoder/combine.sh b/contrib/single_file_decoder/combine.sh index a615b8673a1..ba33155fd83 100755 --- a/contrib/single_file_decoder/combine.sh +++ b/contrib/single_file_decoder/combine.sh @@ -5,12 +5,19 @@ # Note: this POSIX-compliant script is many times slower than the original bash # implementation (due to the grep calls) but it runs and works everywhere. # -# TODO: ROOTS and FOUND as arrays (since they fail on paths with spaces) +# TODO: ROOTS, FOUND, etc., as arrays (since they fail on paths with spaces) +# TODO: revert to Bash-only regex (the grep ones being too slow) # -# Author: Carl Woffenden, Numfum GmbH (released under a CC0 license) +# Author: Carl Woffenden, Numfum GmbH (this script released under a CC0 license/Public Domain) # Common file roots -ROOTS="./" +ROOTS="." + +# -x option excluded includes +XINCS="" + +# -k option includes to keep as include directives +KINCS="" # Files previously visited FOUND="" @@ -18,10 +25,16 @@ FOUND="" # Optional destination file (empty string to write to stdout) DESTN="" +# Whether the "#pragma once" directives should be written to the output +PONCE=0 + # Prints the script usage then exits usage() { - echo "Usage: $0 [-r ] [-o ] infile" - echo " -r file root search paths" + echo "Usage: $0 [-r ] [-x
] [-k
] [-o ] infile" + echo " -r file root search path" + echo " -x file to completely exclude from inlining" + echo " -k file to exclude from inlining but keep the include directive" + echo " -p keep any '#pragma once' directives (removed by default)" echo " -o output file (otherwise stdout)" echo "Example: $0 -r ../my/path - r ../other/path -o out.c in.c" exit 1 @@ -29,10 +42,10 @@ usage() { # Tests that the grep implementation works as expected (older OSX grep fails) test_grep() { - if ! echo '#include "foo"' | grep -Eq '^\s*#\s*include\s*".+"'; then - echo "Aborting: the grep implementation fails to parse include lines" - exit 1 - fi + if ! echo '#include "foo"' | grep -Eq '^\s*#\s*include\s*".+"'; then + echo "Aborting: the grep implementation fails to parse include lines" + exit 1 + fi } # Tests if list $1 has item $2 (returning zero on a match) @@ -57,34 +70,54 @@ write_line() { add_file() { # Match the path local file= - if [ -f "$1" ]; then - file="$1" - else - for root in $ROOTS; do - if test -f "$root/$1"; then - file="$root/$1" - fi - done - fi + for root in $ROOTS; do + if [ -f "$root/$1" ]; then + file="$root/$1" + fi + done if [ -n "$file" ]; then + if [ -n "$DESTN" ]; then + # Log but only if not writing to stdout + echo "Processing: $file" + fi # Read the file local line= while IFS= read -r line; do if echo "$line" | grep -Eq '^\s*#\s*include\s*".+"'; then # We have an include directive so strip the (first) file local inc=$(echo "$line" | grep -Eo '".*"' | grep -Eo '\w*(\.?\w+)+' | head -1) - if ! list_has_item "$FOUND" "$inc"; then - # And we've not previously encountered it - FOUND="$FOUND $inc" - write_line "/**** start inlining $inc ****/" - add_file "$inc" - write_line "/**** ended inlining $inc ****/" + if list_has_item "$XINCS" "$inc"; then + # The file was excluded so error if the source attempts to use it + write_line "#error Using excluded file: $inc" else - write_line "/**** skipping file: $inc ****/" + if ! list_has_item "$FOUND" "$inc"; then + # The file was not previously encountered + FOUND="$FOUND $inc" + if list_has_item "$KINCS" "$inc"; then + # But the include was flagged to keep as included + write_line "/**** *NOT* inlining $inc ****/" + write_line "$line" + else + # The file was neither excluded nor seen before so inline it + write_line "/**** start inlining $inc ****/" + add_file "$inc" + write_line "/**** ended inlining $inc ****/" + fi + else + write_line "/**** skipping file: $inc ****/" + fi fi else - # Otherwise write the source line - write_line "$line" + # Skip any 'pragma once' directives, otherwise write the source line + local write=$PONCE + if [ $write -eq 0 ]; then + if echo "$line" | grep -Eqv '^\s*#\s*pragma\s*once\s*'; then + write=1 + fi + fi + if [ $write -ne 0 ]; then + write_line "$line" + fi fi done < "$file" else @@ -92,10 +125,19 @@ add_file() { fi } -while getopts ":r:o:" opts; do +while getopts ":r:x:k:po:" opts; do case $opts in r) - ROOTS="$OPTARG $ROOTS" + ROOTS="$ROOTS $OPTARG" + ;; + x) + XINCS="$XINCS $OPTARG" + ;; + k) + KINCS="$KINCS $OPTARG" + ;; + p) + PONCE=1 ;; o) DESTN="$OPTARG" diff --git a/contrib/single_file_decoder/create_single_file_decoder.sh b/contrib/single_file_decoder/create_single_file_decoder.sh index ad976bb8be2..ad249ccd799 100755 --- a/contrib/single_file_decoder/create_single_file_decoder.sh +++ b/contrib/single_file_decoder/create_single_file_decoder.sh @@ -3,7 +3,6 @@ # Where to find the sources ZSTD_SRC_ROOT="../../lib" - # Amalgamate the sources echo "Amalgamating files... this can take a while" ./combine.sh -r "$ZSTD_SRC_ROOT" -r "$ZSTD_SRC_ROOT/common" -r "$ZSTD_SRC_ROOT/decompress" -o zstddeclib.c zstddeclib-in.c diff --git a/contrib/single_file_decoder/create_single_file_library.sh b/contrib/single_file_decoder/create_single_file_library.sh new file mode 100755 index 00000000000..68bbfbd2729 --- /dev/null +++ b/contrib/single_file_decoder/create_single_file_library.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Where to find the sources +ZSTD_SRC_ROOT="../../lib" + +# Amalgamate the sources +echo "Amalgamating files... this can take a while" +./combine.sh -r "$ZSTD_SRC_ROOT" -r "$ZSTD_SRC_ROOT/common" -r "$ZSTD_SRC_ROOT/compress" -r "$ZSTD_SRC_ROOT/decompress" -k zstd.h -o zstd.c zstd-in.c +# Did combining work? +if [ $? -ne 0 ]; then + echo "Combine script: FAILED" + exit 1 +fi +echo "Combine script: PASSED" diff --git a/contrib/single_file_decoder/examples/README.md b/contrib/single_file_decoder/examples/README.md index f1223fef1c5..e93bee35f1e 100644 --- a/contrib/single_file_decoder/examples/README.md +++ b/contrib/single_file_decoder/examples/README.md @@ -6,4 +6,6 @@ The examples `#include` the generated `zstddeclib.c` directly but work equally a `emscripten.c` is a bare-bones [Emscripten](https://github.com/emscripten-core/emscripten) compiled WebGL demo using Zstd to further compress a DXT1 texture (see the [original PNG image](testcard.png)). The 256x256 texture would normally be 32kB, but even when bundled with the Zstd decompressor the resulting WebAssembly weighs in at 41kB (`shell.html` is a support file to run the Wasm). -The example files in this directory are released under a [Creative Commons Zero license](https://creativecommons.org/publicdomain/zero/1.0/). +`roundtrip.c` is an example to use with the optional [amalgamated library](../create_single_file_library.sh) showing compression the decompression. + +The example files in this directory are released under a [Creative Commons Zero license](https://creativecommons.org/publicdomain/zero/1.0/) (or Public Domain, whichever is applicable in your jurisdiction). diff --git a/contrib/single_file_decoder/examples/emscripten.c b/contrib/single_file_decoder/examples/emscripten.c index fe6f069a3a3..10dae86899a 100644 --- a/contrib/single_file_decoder/examples/emscripten.c +++ b/contrib/single_file_decoder/examples/emscripten.c @@ -35,267 +35,7 @@ * See \c testcard.png for the original. */ static uint8_t const srcZstd[] = { - 0x28, 0xb5, 0x2f, 0xfd, 0x60, 0x00, 0x7f, 0x6d, 0x61, 0x00, 0x0a, 0x66, - 0xec, 0x17, 0x48, 0x60, 0x1c, 0x5a, 0xc9, 0x5d, 0x1a, 0x38, 0x07, 0xe8, - 0xc5, 0x82, 0x99, 0x68, 0xe6, 0x95, 0x45, 0x58, 0x0d, 0x0c, 0xf3, 0x36, - 0xc8, 0xd9, 0x0f, 0x46, 0x2d, 0x68, 0x11, 0xf8, 0x31, 0x10, 0xa1, 0x1a, - 0x2f, 0x99, 0x5c, 0x84, 0xfd, 0x92, 0x02, 0xe6, 0x3b, 0x44, 0x9b, 0x01, - 0x5d, 0x92, 0xff, 0x38, 0x26, 0x00, 0x6a, 0x6b, 0xc3, 0x53, 0xb2, 0x0c, - 0x25, 0xf3, 0xd8, 0x59, 0x68, 0x9b, 0x14, 0x8a, 0x89, 0x75, 0x18, 0x03, - 0x1d, 0xc9, 0x0f, 0x63, 0x01, 0x73, 0x01, 0x72, 0x01, 0x4f, 0x66, 0x31, - 0x58, 0x0f, 0x97, 0x4b, 0x0c, 0x4c, 0x06, 0xac, 0x07, 0x0b, 0x68, 0xd4, - 0xad, 0x80, 0x64, 0x13, 0x74, 0xa1, 0x12, 0x16, 0x58, 0xcf, 0x1a, 0x95, - 0x5f, 0x0d, 0x26, 0x55, 0xd0, 0x9c, 0xf4, 0x52, 0x35, 0x2e, 0x20, 0xc1, - 0x06, 0x69, 0x03, 0x0a, 0x93, 0x83, 0x5e, 0x27, 0x9b, 0x4c, 0x6d, 0xee, - 0x87, 0x03, 0x30, 0x6c, 0x46, 0xd7, 0x50, 0x5c, 0xca, 0xe6, 0xa6, 0x4d, - 0xa8, 0xf6, 0xab, 0xd7, 0x0e, 0x27, 0x27, 0x90, 0xc4, 0xb2, 0xd1, 0x10, - 0xfa, 0x43, 0x82, 0xc8, 0xf2, 0xe5, 0xff, 0xff, 0xd5, 0x52, 0x62, 0x43, - 0x87, 0x26, 0x2a, 0x05, 0x70, 0x0e, 0xb0, 0x2f, 0xc4, 0x56, 0xef, 0xb5, - 0xca, 0xb8, 0x53, 0xb7, 0x96, 0x0e, 0xe7, 0x00, 0x2c, 0xa8, 0xda, 0x3b, - 0x07, 0x70, 0xa7, 0x78, 0x38, 0x60, 0x87, 0x7a, 0x01, 0x3b, 0x75, 0xec, - 0xfa, 0x77, 0xe2, 0x46, 0x94, 0x61, 0x8e, 0x0d, 0x0c, 0xfb, 0xe7, 0x8b, - 0x13, 0x50, 0x31, 0xa9, 0x27, 0xcd, 0x27, 0xef, 0x6b, 0xa6, 0xab, 0x9c, - 0x4d, 0x95, 0x6c, 0x3a, 0xbb, 0x8e, 0x96, 0x92, 0x18, 0x5a, 0x7c, 0x4f, - 0xff, 0x7b, 0x38, 0xf2, 0xdb, 0x86, 0xde, 0xff, 0x1f, 0x2f, 0x21, 0x86, - 0x7d, 0xbf, 0x45, 0xd0, 0x6e, 0x77, 0x0a, 0xee, 0x0a, 0xee, 0x14, 0x9a, - 0xb8, 0x84, 0xf3, 0xac, 0xbe, 0xc8, 0x7f, 0x8d, 0xff, 0xff, 0xcf, 0x2a, - 0xfb, 0x69, 0xfc, 0xfb, 0xfd, 0x7a, 0x10, 0x22, 0x36, 0xfc, 0xff, 0x3f, - 0xcf, 0xd0, 0xf1, 0x7f, 0xfe, 0xff, 0x3d, 0x24, 0xdf, 0x78, 0x4a, 0xff, - 0xda, 0x9c, 0x39, 0xcf, 0xef, 0xe7, 0xfd, 0x52, 0x98, 0xb5, 0x40, 0x92, - 0xee, 0xdd, 0x99, 0xf5, 0x53, 0x5b, 0x65, 0x6b, 0xb5, 0xd8, 0x7b, 0xae, - 0xfa, 0xc1, 0x0f, 0x0c, 0x7f, 0x4f, 0x55, 0xa3, 0xad, 0x2c, 0xa0, 0xbd, - 0xf7, 0x2a, 0x0e, 0xe8, 0xbd, 0xc7, 0x5e, 0xf5, 0xd8, 0x54, 0x9e, 0x56, - 0xa3, 0xd6, 0x59, 0xd5, 0xfe, 0x1f, 0xc0, 0x30, 0x8c, 0xfc, 0x46, 0x04, - 0xae, 0x60, 0xbc, 0xe8, 0xcf, 0xec, 0x3d, 0xde, 0xf9, 0xf0, 0xfe, 0xef, - 0x7d, 0xcc, 0xf7, 0x2b, 0xe5, 0x1b, 0x70, 0xff, 0xff, 0x7e, 0x3f, 0x6e, - 0xe4, 0x02, 0x07, 0xfc, 0x1b, 0x7a, 0xff, 0xe7, 0x58, 0xfc, 0x7e, 0x3a, - 0xdc, 0x97, 0xfd, 0x57, 0xef, 0xa3, 0xfc, 0x2a, 0xc7, 0x4d, 0xf3, 0xcb, - 0x9d, 0xce, 0xac, 0xfe, 0xeb, 0x2e, 0x86, 0xb9, 0x69, 0x54, 0xef, 0xf9, - 0x55, 0xcf, 0xff, 0x48, 0x24, 0x72, 0x3a, 0x9d, 0x72, 0x2f, 0x2f, 0x2f, - 0xff, 0x3f, 0xe7, 0x01, 0x6c, 0x4d, 0x6c, 0xcd, 0x2d, 0x5b, 0x53, 0xb7, - 0x59, 0x22, 0x08, 0x0b, 0xa7, 0x92, 0x15, 0x75, 0x93, 0xb0, 0x5d, 0xaf, - 0x2a, 0x63, 0x95, 0x1d, 0x25, 0xd2, 0xd2, 0xa8, 0x1c, 0x84, 0xc9, 0xdc, - 0x72, 0xba, 0xd7, 0xfc, 0x69, 0xf5, 0xc7, 0x19, 0xa9, 0xbe, 0xfa, 0x26, - 0x55, 0x25, 0x75, 0xb7, 0x60, 0xa3, 0xd8, 0x68, 0x54, 0xb7, 0x1b, 0xa5, - 0x54, 0x62, 0xb1, 0x49, 0xde, 0xe2, 0xac, 0xa2, 0xe8, 0x7b, 0xff, 0x5f, - 0x75, 0x4e, 0xb8, 0xa2, 0xdd, 0x6a, 0xb7, 0xda, 0x6e, 0x2e, 0x04, 0xcd, - 0x08, 0x2f, 0xec, 0x8e, 0x49, 0xaf, 0x49, 0x6f, 0x8b, 0x4f, 0x2e, 0x1a, - 0xc5, 0x62, 0x7b, 0x6b, 0x3e, 0x32, 0x3e, 0x32, 0xbe, 0x08, 0x35, 0x4d, - 0x63, 0x93, 0xa6, 0xc8, 0x42, 0xe6, 0x21, 0xcc, 0x59, 0xc8, 0x4c, 0xe5, - 0x86, 0xe1, 0x03, 0x06, 0xa4, 0xec, 0xff, 0xb7, 0x78, 0x7e, 0x62, 0x43, - 0xc7, 0x2c, 0x50, 0x30, 0x4a, 0xc8, 0x9b, 0xf3, 0xbf, 0xe6, 0x62, 0xa0, - 0x50, 0xa6, 0x9c, 0xe3, 0x6e, 0x5b, 0xaf, 0x77, 0x8b, 0xbb, 0xe1, 0x70, - 0xaa, 0xaa, 0xaa, 0x92, 0xb4, 0x52, 0xad, 0x14, 0x87, 0x93, 0x0b, 0xe6, - 0x82, 0x39, 0x11, 0xb9, 0x20, 0x9a, 0x16, 0x34, 0x22, 0x68, 0xb2, 0x68, - 0xb2, 0x76, 0xd3, 0xe8, 0x6e, 0xda, 0x6b, 0x62, 0x34, 0x2e, 0x8d, 0xbd, - 0x2d, 0x3d, 0x6b, 0x4c, 0x26, 0x33, 0xda, 0x33, 0xf3, 0x91, 0x51, 0x46, - 0x79, 0xbd, 0x3e, 0x39, 0x9f, 0xcf, 0xd2, 0xb8, 0x5c, 0xfa, 0x22, 0xf8, - 0x8e, 0xb6, 0xbe, 0x08, 0x40, 0x14, 0x49, 0x40, 0x14, 0xf2, 0x0c, 0x2d, - 0x30, 0x85, 0x3c, 0x63, 0x29, 0xd3, 0x98, 0x85, 0x6c, 0xb5, 0xdb, 0xad, - 0x5c, 0x63, 0x9e, 0x72, 0xcf, 0x43, 0xe6, 0xaf, 0x77, 0xa6, 0xe2, 0x21, - 0x0c, 0x4d, 0xd3, 0x49, 0x1e, 0xc2, 0x14, 0x6f, 0xee, 0xdb, 0x7b, 0x7b, - 0x08, 0xb3, 0xa4, 0x60, 0x3b, 0x9d, 0x6e, 0x8b, 0x37, 0x4b, 0x0a, 0x74, - 0x35, 0x33, 0xbc, 0xf9, 0x64, 0x85, 0x63, 0x32, 0x29, 0x20, 0x59, 0x0c, - 0x3c, 0x96, 0x67, 0x62, 0xb7, 0x8a, 0x92, 0x4d, 0xa0, 0xd3, 0xf3, 0xd1, - 0x85, 0x80, 0x38, 0xcb, 0x64, 0x60, 0xc9, 0xb5, 0xaf, 0x97, 0x8d, 0x20, - 0x45, 0x28, 0xb8, 0xab, 0xe8, 0xc9, 0x0a, 0x88, 0x1f, 0xd6, 0x47, 0x54, - 0xf1, 0xd3, 0xfb, 0x62, 0xa7, 0xfd, 0xf2, 0x8b, 0xfd, 0xb6, 0xe4, 0x2e, - 0xb6, 0x91, 0x73, 0x1c, 0xd0, 0x7b, 0xba, 0x83, 0xc9, 0xac, 0x51, 0x39, - 0x92, 0xc5, 0x4f, 0x30, 0x1e, 0x2e, 0xd5, 0xf1, 0xa8, 0xa6, 0xa5, 0x80, - 0x70, 0xb9, 0xbc, 0xb7, 0xc2, 0x52, 0x32, 0x6c, 0xe3, 0x3d, 0xed, 0x41, - 0xa4, 0x4b, 0x31, 0x2a, 0xe6, 0x62, 0x11, 0x19, 0x95, 0x73, 0x1d, 0xbf, - 0xe1, 0x6c, 0xfc, 0x47, 0x75, 0x6c, 0x37, 0x63, 0x02, 0xf8, 0x34, 0x40, - 0x9a, 0x00, 0x1d, 0xf7, 0x32, 0x56, 0x77, 0xda, 0x5b, 0x9f, 0x9f, 0x0f, - 0xbb, 0x91, 0x5b, 0xbd, 0xe7, 0x58, 0x82, 0x4a, 0x20, 0xcd, 0x4f, 0x47, - 0x15, 0xf3, 0x51, 0xf1, 0x43, 0x51, 0x10, 0x96, 0xae, 0xba, 0xf7, 0x21, - 0x50, 0xef, 0x55, 0x27, 0x0c, 0x1f, 0xe0, 0x54, 0xf8, 0xc9, 0x69, 0xef, - 0xb9, 0x53, 0xf7, 0x83, 0x73, 0x9d, 0xce, 0x86, 0x07, 0x83, 0x44, 0x61, - 0x37, 0x35, 0x35, 0x33, 0x4e, 0x33, 0x33, 0x3e, 0x9f, 0x50, 0x48, 0x24, - 0xe6, 0xd0, 0x79, 0x49, 0xc3, 0x2d, 0xa0, 0x46, 0x31, 0x9a, 0x72, 0xc3, - 0x84, 0xff, 0x7a, 0x95, 0xbb, 0x00, 0x22, 0xcc, 0x14, 0x00, 0x04, 0xac, - 0x60, 0x64, 0x86, 0xe4, 0x6f, 0xb1, 0x58, 0xf4, 0xdc, 0xb0, 0x05, 0x00, - 0x72, 0x38, 0xf8, 0xce, 0xce, 0x8e, 0xcf, 0x37, 0x33, 0x43, 0x24, 0x0a, - 0x85, 0x33, 0x35, 0x35, 0x37, 0xc2, 0xa8, 0x28, 0x27, 0x1b, 0x9d, 0xce, - 0x29, 0x18, 0xe4, 0xfc, 0x09, 0x53, 0xa5, 0x51, 0xad, 0x74, 0x79, 0x7b, - 0xb5, 0x4a, 0x65, 0x94, 0x36, 0x89, 0xf5, 0x62, 0x9b, 0xd8, 0x9a, 0xe8, - 0x2b, 0xff, 0xa1, 0x73, 0xfe, 0x2e, 0x2c, 0x41, 0x45, 0x37, 0xef, 0x6e, - 0x7b, 0x38, 0xca, 0xa5, 0xd2, 0xb8, 0x1c, 0x3b, 0x96, 0x21, 0xbb, 0x5d, - 0xad, 0xd1, 0xdb, 0x1c, 0xf6, 0x5e, 0x4b, 0xd9, 0x59, 0x1b, 0x67, 0xf5, - 0x7a, 0x7c, 0x9a, 0x91, 0x3e, 0x8e, 0xe3, 0xee, 0x7b, 0xb9, 0xa4, 0xb9, - 0xf5, 0x70, 0xee, 0x1d, 0x4e, 0x4f, 0xcc, 0xd6, 0x7b, 0x07, 0x71, 0x48, - 0xf2, 0x06, 0xd0, 0x10, 0x82, 0x21, 0xe4, 0x55, 0x2e, 0xa5, 0x1d, 0xbe, - 0x48, 0x8c, 0x69, 0xbb, 0x24, 0x40, 0x68, 0x9b, 0xba, 0x5a, 0x5a, 0xa7, - 0xe2, 0xd1, 0xac, 0xc2, 0xd8, 0x87, 0x9c, 0xe3, 0x78, 0xee, 0xa6, 0xcd, - 0xdd, 0x68, 0x6e, 0xdd, 0xdb, 0x2e, 0xc6, 0xbb, 0x8b, 0xe9, 0xc1, 0xd9, - 0xf6, 0x62, 0x7e, 0x72, 0x7e, 0x72, 0x34, 0xe4, 0x68, 0xc8, 0x11, 0x32, - 0x10, 0x32, 0x20, 0x32, 0xf0, 0x12, 0x19, 0x90, 0xe0, 0x45, 0x91, 0xe0, - 0x25, 0x83, 0xba, 0xc9, 0x20, 0x26, 0x87, 0xa5, 0x72, 0xa9, 0x64, 0x72, - 0x80, 0x21, 0x54, 0x13, 0xeb, 0x29, 0x18, 0x42, 0x34, 0x84, 0x94, 0x34, - 0x84, 0xa4, 0x1d, 0xa4, 0x1d, 0x82, 0x1c, 0xef, 0xaf, 0x0e, 0x63, 0x47, - 0x6d, 0x10, 0xb9, 0xec, 0xd8, 0x2d, 0x3b, 0x9e, 0x21, 0xb1, 0x67, 0x48, - 0x34, 0x24, 0x1a, 0x52, 0xdb, 0xa4, 0x6d, 0x62, 0xd3, 0xfa, 0xff, 0xfa, - 0x03, 0x34, 0xef, 0x9d, 0xc9, 0xe1, 0x5d, 0xec, 0xf5, 0xf1, 0x79, 0x8c, - 0x97, 0xd2, 0x24, 0xc1, 0x2d, 0xe0, 0x39, 0x16, 0x1e, 0xa9, 0x41, 0xc3, - 0xbf, 0x4a, 0xd9, 0x3c, 0xea, 0x77, 0x96, 0x55, 0xe6, 0x95, 0xc3, 0xf1, - 0x8e, 0x7b, 0x4f, 0xad, 0x61, 0xf8, 0xe7, 0x01, 0xad, 0x46, 0xf5, 0x2c, - 0xac, 0x55, 0x2c, 0x94, 0xaa, 0x46, 0xfb, 0x5e, 0xcd, 0xaa, 0x1f, 0x78, - 0x4f, 0x2f, 0xd1, 0xc9, 0x02, 0xd6, 0x2c, 0x67, 0xef, 0x3f, 0x54, 0xab, - 0xda, 0x03, 0x79, 0x1f, 0xab, 0xfd, 0x0c, 0x38, 0x3c, 0xbc, 0xe1, 0xd5, - 0x01, 0xf6, 0xfb, 0xfb, 0xf1, 0x70, 0xee, 0xfd, 0x90, 0x13, 0x97, 0xc4, - 0xbc, 0x08, 0xe7, 0x4b, 0x88, 0x34, 0xf7, 0x56, 0x1e, 0x0c, 0xdb, 0xe4, - 0x9c, 0x78, 0xf1, 0xf4, 0x62, 0x4c, 0xb5, 0xf7, 0xdd, 0xd9, 0x4c, 0x5a, - 0x69, 0xa6, 0x36, 0x27, 0x03, 0xbe, 0x86, 0xc2, 0x72, 0xa2, 0x60, 0x73, - 0xf1, 0xe0, 0x17, 0x50, 0xb5, 0x93, 0x81, 0xac, 0xf1, 0xc9, 0xd4, 0x66, - 0x73, 0x71, 0xce, 0x63, 0xa8, 0x60, 0x98, 0xda, 0x86, 0x46, 0x72, 0xec, - 0x54, 0xc1, 0xe6, 0x8a, 0x10, 0x23, 0x2d, 0x0c, 0xdd, 0x44, 0x0b, 0xa0, - 0x44, 0xa4, 0x9d, 0x0e, 0x64, 0x31, 0x30, 0x45, 0xb1, 0x97, 0x4c, 0x6d, - 0x9f, 0x43, 0x99, 0x71, 0xa8, 0x9a, 0xe6, 0xbd, 0x3a, 0xe1, 0xff, 0x7f, - 0x33, 0x61, 0xf1, 0x48, 0xda, 0x48, 0x28, 0x10, 0x23, 0x9b, 0x24, 0xeb, - 0xee, 0xbd, 0x35, 0x0e, 0x6e, 0x75, 0x23, 0x20, 0xd6, 0x95, 0x8c, 0xa5, - 0x24, 0xec, 0x44, 0x67, 0x52, 0x2e, 0x78, 0x2a, 0xba, 0x3e, 0x3a, 0x4e, - 0xc9, 0x5c, 0x23, 0xb0, 0xd5, 0xfb, 0x29, 0xaf, 0x9a, 0x0b, 0x90, 0x89, - 0xd8, 0xec, 0xa9, 0xa8, 0x13, 0xfc, 0x22, 0xfa, 0xf2, 0x74, 0x2f, 0x4e, - 0x35, 0xb0, 0x6d, 0x6c, 0xfd, 0xc4, 0xfe, 0xd0, 0x98, 0x3d, 0xe5, 0x43, - 0x0a, 0xd0, 0x33, 0x26, 0x3b, 0x12, 0x7d, 0x65, 0xa1, 0xff, 0xff, 0x6f, - 0x53, 0x0e, 0x28, 0x84, 0xa7, 0xa2, 0x2e, 0xf8, 0x4a, 0xb6, 0xa1, 0x47, - 0xf5, 0xd0, 0x13, 0x9d, 0xd9, 0x50, 0xef, 0x9f, 0x31, 0xb4, 0x13, 0x67, - 0xf9, 0x0a, 0x99, 0xb5, 0x80, 0xec, 0x4a, 0x1a, 0x59, 0x21, 0x3b, 0xce, - 0xc5, 0x7e, 0x96, 0x85, 0x92, 0xc5, 0xb0, 0x75, 0xaa, 0x41, 0x16, 0xa9, - 0xd3, 0xde, 0x13, 0x7d, 0xd9, 0x61, 0x30, 0x1c, 0x73, 0x61, 0x54, 0x90, - 0xcf, 0xd4, 0xe8, 0xfe, 0xbf, 0xbf, 0x36, 0x57, 0x26, 0x38, 0xab, 0x06, - 0xc4, 0x7e, 0x3c, 0x5b, 0x35, 0xd2, 0x7c, 0x2c, 0x0a, 0x82, 0xf2, 0xa8, - 0xf2, 0x8b, 0x48, 0xa9, 0x90, 0x00, 0x01, 0x10, 0x10, 0x14, 0x04, 0x00, - 0x32, 0xa2, 0x06, 0x82, 0x28, 0x90, 0xc2, 0xb4, 0x85, 0xda, 0x01, 0x52, - 0xe9, 0x18, 0x85, 0x60, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x14, 0x41, 0x00, - 0x40, 0xa0, 0x04, 0x40, 0x00, 0x80, 0x50, 0x03, 0x01, 0x10, 0x18, 0x01, - 0x80, 0xd4, 0x14, 0x99, 0x01, 0xfd, 0x07, 0xf8, 0x16, 0x0e, 0xd9, 0x5d, - 0xa3, 0x70, 0xfe, 0xda, 0x17, 0xfa, 0xce, 0x46, 0x9a, 0x99, 0x81, 0x1a, - 0x39, 0xba, 0x63, 0xb1, 0x18, 0x11, 0x58, 0xd7, 0xc7, 0xba, 0x03, 0x3e, - 0x01, 0xf2, 0xf9, 0x4e, 0x12, 0xa3, 0x50, 0x7b, 0xaf, 0x7b, 0x60, 0x5c, - 0x83, 0x23, 0xd2, 0x60, 0x27, 0x84, 0xad, 0xb8, 0x02, 0xed, 0xfe, 0xb4, - 0x9c, 0x08, 0x9f, 0x49, 0xae, 0x55, 0x02, 0x94, 0xc0, 0x1b, 0x90, 0x75, - 0x0b, 0x90, 0xc4, 0xc7, 0x43, 0x9e, 0x67, 0x25, 0x70, 0x61, 0x0d, 0xb8, - 0x7a, 0x97, 0x43, 0xfc, 0xd1, 0x7e, 0x68, 0xed, 0x03, 0xb7, 0x1e, 0x75, - 0xe9, 0x4d, 0x7a, 0x23, 0x18, 0x37, 0x63, 0x6f, 0xab, 0x5f, 0x7c, 0x5b, - 0x1c, 0x05, 0xdf, 0x3f, 0x00, 0x86, 0x37, 0xa0, 0xfa, 0x0c, 0xe0, 0xed, - 0x35, 0x35, 0x2f, 0xd8, 0xd1, 0x75, 0xba, 0x37, 0x34, 0x7e, 0xb0, 0x84, - 0x2a, 0x01, 0x0c, 0x98, 0xed, 0x47, 0xf9, 0x86, 0x81, 0x74, 0x00, 0x5d, - 0x8b, 0x4c, 0x18, 0x8a, 0x31, 0xcd, 0xae, 0x07, 0x44, 0xb5, 0xd5, 0x07, - 0xa0, 0xdf, 0xf4, 0xfa, 0xa6, 0x42, 0xd0, 0x4f, 0x17, 0xd8, 0xdf, 0xb6, - 0x34, 0x44, 0xe3, 0x01, 0xc4, 0xb6, 0x2d, 0xb5, 0x56, 0xc6, 0x2a, 0x1f, - 0x05, 0x6c, 0x35, 0xe0, 0x09, 0x31, 0xef, 0x60, 0xfe, 0xaf, 0x07, 0x80, - 0x32, 0xa0, 0xe9, 0xd3, 0x96, 0x45, 0xa7, 0xaa, 0xb6, 0xfb, 0x03, 0x10, - 0xe3, 0x97, 0x96, 0x8d, 0x3a, 0x01, 0xdd, 0x58, 0x58, 0x78, 0x00, 0xab, - 0xff, 0x06, 0xa0, 0xd6, 0x01, 0x58, 0x08, 0xb7, 0xdc, 0x2d, 0xa7, 0xfb, - 0x22, 0xa8, 0x67, 0x00, 0xe3, 0xcf, 0x82, 0x43, 0xfc, 0x96, 0x1b, 0x40, - 0x63, 0xcf, 0x9d, 0x42, 0x5d, 0x66, 0x40, 0xaa, 0xaf, 0x28, 0x94, 0xd3, - 0x2a, 0xd4, 0x02, 0x13, 0xd2, 0xdf, 0x03, 0x9c, 0x60, 0x6b, 0x16, 0x94, - 0xb4, 0xbe, 0x62, 0xc2, 0x35, 0x60, 0x45, 0x09, 0x23, 0x5a, 0xe0, 0x85, - 0xb3, 0x03, 0x50, 0x68, 0x0c, 0x20, 0xa5, 0xf9, 0x94, 0xd2, 0x35, 0x80, - 0xad, 0x4c, 0x4e, 0x40, 0x41, 0x97, 0x92, 0x75, 0xbe, 0x0c, 0x03, 0x50, - 0x85, 0x08, 0xaf, 0x36, 0x00, 0x68, 0xaf, 0x09, 0xb3, 0x0c, 0x20, 0x4f, - 0x81, 0x6a, 0x6a, 0xf5, 0x0d, 0x70, 0x69, 0x00, 0x4c, 0xb4, 0x0f, 0x59, - 0xe7, 0x31, 0x0a, 0x45, 0x9f, 0xde, 0x90, 0xd6, 0x38, 0x80, 0x6b, 0x2c, - 0xb9, 0x2f, 0xd4, 0x01, 0x40, 0x14, 0xd5, 0xed, 0x8e, 0x01, 0x53, 0xbf, - 0x03, 0x18, 0x1e, 0xb0, 0xc1, 0x85, 0x32, 0xec, 0x78, 0x2b, 0xf0, 0xbb, - 0xbb, 0x6c, 0xf3, 0x4d, 0xdc, 0x73, 0x40, 0xfd, 0x10, 0x09, 0x9e, 0x20, - 0xe2, 0x12, 0x8c, 0xe0, 0xd2, 0xed, 0x80, 0x6b, 0xcc, 0x78, 0x20, 0x03, - 0xd0, 0x5e, 0x06, 0xf4, 0xb0, 0xc4, 0x0e, 0x15, 0x1d, 0x80, 0xb4, 0x76, - 0xdf, 0x49, 0x03, 0x50, 0x82, 0xad, 0xda, 0x8b, 0x5a, 0x61, 0xc2, 0x5e, - 0xb5, 0x1e, 0x46, 0xc0, 0xde, 0xaa, 0x0e, 0x15, 0x06, 0xd2, 0xf4, 0xb2, - 0xd1, 0xed, 0x38, 0x0a, 0x03, 0x18, 0x33, 0x1a, 0x80, 0x61, 0x3e, 0xec, - 0x7c, 0x74, 0xa8, 0x1d, 0x80, 0x1a, 0xce, 0x25, 0x1d, 0x41, 0xd1, 0xc1, - 0x03, 0x28, 0xb5, 0xaf, 0x72, 0x9c, 0x59, 0x7a, 0xe1, 0x7d, 0xc0, 0xa5, - 0x08, 0x1e, 0x18, 0x24, 0xfa, 0xbd, 0x99, 0x4a, 0x31, 0xa0, 0xea, 0xee, - 0xf8, 0x36, 0x60, 0x98, 0xc9, 0x10, 0xd1, 0xa7, 0x35, 0x00, 0x8d, 0x40, - 0x8e, 0x5a, 0x35, 0x0f, 0x80, 0xb1, 0xd4, 0x32, 0x79, 0x40, 0x34, 0x05, - 0x7e, 0x98, 0xc6, 0x80, 0x3e, 0x90, 0x01, 0x65, 0xf4, 0x80, 0x73, 0x08, - 0x64, 0xd7, 0x36, 0xc1, 0x7c, 0xc0, 0x5c, 0x75, 0x00, 0xc5, 0x09, 0x58, - 0x9c, 0x13, 0x01, 0x72, 0x37, 0x9b, 0x79, 0xe4, 0x05, 0xd1, 0x01, 0x04, - 0x98, 0x08, 0x74, 0xfd, 0xfc, 0x3f, 0x1c, 0x00, 0x73, 0x01, 0xfc, 0x1c, - 0xcc, 0x16, 0x43, 0x19, 0x1d, 0xac, 0x61, 0x4b, 0x11, 0xc2, 0xa0, 0xf2, - 0x01, 0x0b, 0x7b, 0x3b, 0xf4, 0xfc, 0x58, 0x5d, 0x2d, 0x5c, 0x01, 0x8c, - 0x62, 0x17, 0x78, 0xbe, 0x60, 0x8c, 0x01, 0x6f, 0x91, 0x49, 0x65, 0x54, - 0x92, 0xe9, 0x01, 0x1e, 0x10, 0x77, 0x35, 0x00, 0xa8, 0xd4, 0xc7, 0x71, - 0x07, 0xd8, 0xcd, 0xa3, 0x7d, 0x69, 0x20, 0xac, 0x07, 0x00, 0x35, 0xc7, - 0x62, 0xee, 0x8c, 0x7d, 0x0c, 0xb8, 0x43, 0x0e, 0x00, 0x08, 0xfb, 0xe7, - 0xec, 0x33, 0x37, 0x04, 0x80, 0x2d, 0x1d, 0xa6, 0x13, 0x34, 0x1b, 0x1d, - 0xc0, 0xca, 0x00, 0x92, 0xed, 0x2e, 0x56, 0xbe, 0x91, 0x80, 0x0c, 0x88, - 0xa6, 0x01, 0xdf, 0x7f, 0x90, 0x49, 0xed, 0x0c, 0xe0, 0x08, 0x73, 0x28, - 0x74, 0xc7, 0xe1, 0xb1, 0x03, 0x5d, 0xc5, 0xab, 0x61, 0x42, 0xdf, 0x03, - 0x43, 0xf3, 0x35, 0x04, 0xcf, 0xc6, 0x1d, 0x79, 0x07, 0x40, 0x22, 0xe4, - 0x68, 0x0d, 0x01, 0x95, 0xad, 0x72, 0x69, 0x00, 0x39, 0x9d, 0x53, 0x8f, - 0x13, 0x0d, 0xb0, 0x29, 0x79, 0x1a, 0x39, 0x20, 0x12, 0x28, 0x9b, 0x02, - 0x8f, 0x74, 0x90, 0x4c, 0xe8, 0xd1, 0x57, 0xf4, 0x01, 0x44, 0x04, 0xe0, - 0x0c, 0x82, 0x91, 0xc5, 0x4f, 0x8f, 0xc6, 0x00, 0x43, 0x85, 0x65, 0xc8, - 0xe6, 0x34, 0x1d, 0x80, 0xc0, 0xca, 0xdb, 0x57, 0x6c, 0x00, 0x72, 0x42, - 0x5f, 0xd0, 0x49, 0x57, 0x47, 0xd4, 0x97, 0x18, 0x18, 0x80, 0x68, 0x8e, - 0x0a, 0xf1, 0x6b, 0x34, 0xf1, 0x60, 0x2c, 0x41, 0x29, 0xd3, 0x3d, 0x55, - 0x95, 0xb1, 0x3c, 0xd4, 0x95, 0x42, 0xef, 0xe7, 0xca, 0x00, 0x2e, 0xce, - 0x25, 0xc2, 0xca, 0xf5, 0x00, 0x17, 0x3b, 0x8c, 0x42, 0x88, 0x03, 0xde, - 0x97, 0xe1, 0x3a, 0x74, 0xb0, 0x33, 0xe0, 0x8f, 0x47, 0xeb, 0x2a, 0x5f, - 0x36, 0x3e, 0x5a, 0xff, 0xc5, 0x80, 0xb9, 0x13, 0xa9, 0x1f, 0xf8, 0x86, - 0xc9, 0x51, 0xf8, 0x4c, 0xaa, 0xe1, 0x65, 0x80, 0xb0, 0x8b, 0x91, 0xec, - 0xcc, 0xbf, 0x70, 0x19, 0x98, 0x03, 0x10, 0xf0, 0x38, 0x40, 0xc4, 0x65, - 0xbe, 0x41, 0xb2, 0x58, 0x3f, 0xe0, 0xcc, 0x0e, 0x08, 0x2b, 0x73, 0xf4, - 0xdd, 0x86, 0x06, 0xa0, 0xc6, 0x8f, 0x1a, 0x32, 0x66, 0x50, 0x8e, 0xe1, - 0x59, 0x67, 0x00, 0xed, 0x66, 0x1d, 0xdd, 0xfa, 0x7b, 0xe2, 0x56, 0x89, - 0xd9, 0xa0, 0x4f, 0x41, 0x94, 0x28, 0xb8, 0xc6, 0xc7, 0x64, 0xde, 0x9b, - 0x64, 0x44, 0x33, 0x39, 0xb5, 0x6c, 0xb9, 0x42, 0xe7, 0x7e, 0x16, 0xd2, - 0x01, 0x12, 0x03, 0xb3, 0x48, 0x47, 0x6b, 0x75, 0x26, 0x19, 0x8c, 0xac, - 0x6f, 0xb1, 0x6f, 0xdc, 0x04, 0x27, 0x3a, 0x00, 0xd6, 0xae, 0xfa, 0xe1, - 0xf7, 0x30, 0xa4, 0xdb, 0xd5, 0x86, 0x5a, 0x07, 0x11, 0xde, 0xea, 0xf4, - 0xb0, 0x83, 0x16, 0xbb, 0xc6, 0x00, 0x6e, 0xf2, 0x6b, 0x40, 0x81, 0x01, - 0x67, 0x0e, 0xa9, 0x82, 0x23, 0x04, 0x34, 0xed, 0x02, 0xf5, 0xe4, 0x0e, - 0x58, 0xe8, 0x8a, 0x58, 0x57, 0xb0, 0x56, 0x65, 0x3d, 0x40, 0x64, 0x03, - 0x6e, 0x7b, 0x07, 0x20, 0x99, 0x90, 0x36, 0x95, 0x9f, 0xdf, 0x3d, 0xe8, - 0x00, 0xa0, 0x57, 0x8f, 0x6d, 0xa4, 0xb3, 0x1d, 0x7a, 0x06, 0xa8, 0x26, - 0x41, 0xb0, 0x8c, 0x9c, 0x10, 0x85, 0x6c, 0xb4, 0x31, 0xa6, 0x5b, 0x7a, - 0x10, 0x51, 0x15, 0x3c, 0xa2, 0x42, 0xd3, 0x23, 0x02, 0xc0, 0x17, 0x7e, - 0x03, 0x28, 0xba, 0xce, 0x9b, 0xae, 0xdd, 0x1a, 0x19, 0xd0, 0x15, 0xac, - 0xeb, 0x20, 0x3c, 0x3a, 0x00, 0xc6, 0xbb, 0x8a, 0xd5, 0x64, 0xc2, 0x21, - 0x1d, 0x6c, 0x15, 0x5a, 0xd3, 0x44, 0x98, 0x14, 0x95, 0xb3, 0xb7, 0xdd, - 0xa6, 0xea, 0x06, 0x54, 0x78, 0xc3, 0xe8, 0x79, 0x9b, 0x86, 0x29, 0x76, - 0x8b, 0x6b, 0xaa, 0x0d, 0xa8, 0x2f, 0x22, 0x2a, 0xeb, 0x68, 0x81, 0x6c, - 0x56, 0xfd, 0x79, 0xac, 0x79, 0x4b, 0xa0, 0x01, 0x3f, 0x17, 0x43, 0x82, - 0xb4, 0xd5, 0x00, 0x14, 0xb7, 0xf5, 0x00, 0xf4, 0x15, 0xa8, 0xd7, 0x4b, - 0xb1, 0xbc, 0xa8, 0x36, 0x98, 0xf0, 0x8c, 0xe7, 0xf4, 0x7b, 0x35, 0xd8, - 0xad, 0x0d, 0x5f, 0x9d, 0x96, 0xab, 0xed, 0x48, 0xe2, 0xdc, 0x1c, 0xbe, - 0x12, 0xfa, 0x41, 0x6f, 0xf5, 0x1e, 0xb6, 0x9f, 0xee, 0xac, 0x21, 0xf4, - 0xf6, 0x00, 0x38, 0xb1, 0x1f, 0xfd, 0xd0, 0x0e, 0xc7, 0xdd, 0xa0, 0x39, - 0x07, 0x8c, 0x35, 0x1f, 0x7e, 0xcc, 0xbf, 0xf6, 0xe0, 0x06, 0x66, 0x7d, - 0x10, 0x3f, 0xc5, 0x3e, 0xde, 0x42, 0xf9, 0x3d, 0x00, 0x54, 0x81, 0x67, - 0x8a, 0xe6, 0x63, 0x0d, 0x01, 0xd0, 0x31, 0xe0, 0x6e, 0xd0, 0xe1, 0x59, - 0xf6, 0x1b, 0xf7, 0x0d, 0x52, 0x06, 0x80, 0x61, 0x4f, 0xe8, 0x77, 0xdd, - 0x6f, 0x48, 0x20, 0x1d, 0xbb, 0x2a, 0x16, 0x8b, 0x54, 0x87, 0x92, 0x83, - 0xe6, 0x8f, 0x55, 0x59, 0x06, 0x00, 0xe9, 0xc5, 0xce, 0x21, 0x63, 0x87, - 0xaf, 0x86, 0xcc, 0xba, 0xd6, 0xe7, 0x00, 0xf6, 0x91, 0x92, 0x92, 0xea, - 0xe8, 0x42, 0x06, 0x69, 0x13, 0xf5, 0x00, 0xd0, 0xb0, 0xa7, 0xcb, 0x4c, - 0xb0, 0xd2, 0x2d, 0x28, 0x63, 0xf0, 0x6a, 0xc7, 0x80, 0x6a, 0x19, 0xb2, - 0x66, 0x51, 0xf3, 0xb1, 0x21, 0xa0, 0x48, 0xad, 0x1e, 0x80, 0x62, 0xaf, - 0x00, 0xf4, 0xa5, 0x4e, 0x83, 0x75, 0x1b, 0xfe, 0x00, 0xc4, 0xcf, 0x55, - 0xb2, 0x50, 0xa6, 0xeb, 0x38, 0xed, 0x8f, 0xd3, 0x1d, 0x00, 0xf6, 0xe3, - 0x90, 0x1c, 0x60, 0x9e, 0x8e, 0xeb, 0x0b, 0xba, 0x44, 0x06, 0x68, 0xbb, - 0xd3, 0x10, 0x63, 0x35, 0xe1, 0x86, 0x5c, 0x5c, 0x2b, 0x85, 0xa6, 0xe7, - 0x38, 0x2c, 0x18, 0x83, 0x1f, 0x8f, 0x9b, 0x8e, 0x4d, 0x26, 0xcd, 0x34, - 0x0c, 0x66, 0x1d, 0x70, 0xb7, 0x01, 0xe6, 0x02, 0xa8, 0x51, 0x63, 0xcf, - 0xbb, 0x03, 0xca, 0x85, 0xc6, 0x9c, 0xf6, 0xf1, 0x51, 0xe0, 0x60, 0x07, - 0x40, 0x86, 0xf0, 0x1e, 0x6e, 0xef, 0x61, 0x10, 0xd9, 0x36, 0xcc, 0xfc, - 0x58, 0xe2, 0x37, 0x0d, 0x58, 0xb7, 0xbe, 0xca, 0xc9, 0xd8, 0xcd, 0xaa, - 0xd5, 0x5b, 0x77, 0x83, 0xcb, 0x0e, 0x30, 0xce, 0xc8, 0xb8, 0xcd, 0xbf, - 0x1e, 0x63, 0x04, 0xad, 0xb7, 0xcd, 0x43, 0x62, 0x4c, 0xe0, 0x1a, 0xd4, - 0x21, 0xe2, 0xdd, 0x33, 0xdf, 0xb1, 0xdd, 0xdc, 0x01, 0x22, 0x18, 0xce, - 0xa1, 0xd8, 0xcb, 0x67, 0xd5, 0x38, 0x4a, 0xbc, 0xd5, 0x81, 0x3d, 0x03, - 0x98, 0x35, 0x60, 0x41, 0x85, 0x0c, 0x1d, 0xe7, 0x76, 0xf8, 0x11, 0x52, - 0x76, 0xf6, 0x06, 0x16, 0x02, 0x45, 0xc8, 0xd8, 0x2f, 0x5e, 0x57, 0xbc, - 0x3b, 0x89, 0x97, 0x09, 0x3e, 0x03, 0x34, 0x1a, 0x9d, 0x37, 0x87, 0x48, - 0x0a, 0xe0, 0xa7, 0x4f, 0x8c, 0x3a, 0xa2, 0xaf, 0xfd, 0x7b, 0x80, 0xcf, - 0xe5, 0x18, 0x61, 0x68, 0xba, 0x61, 0x8b, 0x09, 0xaa, 0xa3, 0x0c, 0x47, - 0x3c, 0x43, 0x03, 0xac, 0xa3, 0x2e, 0x5e, 0x72, 0x0c, 0x80, 0x19, 0x61, - 0xe6, 0x6e, 0x0e, 0xd9, 0xe8, 0xe8, 0xaf, 0x11, 0x9b, 0x4a, 0x73, 0x7a, - 0x61, 0x66, 0xf0, 0x54, 0x1d, 0x18, 0xc8, 0x23, 0x36, 0xbf, 0xb5, 0xf4, - 0x86, 0x54, 0xed, 0xb5, 0x91, 0xee, 0xb8, 0xbc, 0xde, 0xc3, 0x87, 0x9b, - 0x2f, 0x81, 0xf2, 0xee, 0xa3, 0xec, 0x02 +#include "testcard-zstd.inl" }; /** diff --git a/contrib/single_file_decoder/examples/roundtrip.c b/contrib/single_file_decoder/examples/roundtrip.c new file mode 100644 index 00000000000..b228de88e63 --- /dev/null +++ b/contrib/single_file_decoder/examples/roundtrip.c @@ -0,0 +1,83 @@ +/* + * \file roundtrip.c + * In this example we include \c zstd.h and compile separately the amalgamated + * \c zstd.c: + * \code + * cc -Wall -Wextra -Werror -I. -Os -g0 zstd.c examples/roundtrip.c + * \endcode + * + * \author Carl Woffenden, Numfum GmbH (released under a CC0 license) + */ + +#include +#include +#include +#include +#include + +#include "zstd.h" + +//************************** Test Data (DXT texture) **************************/ + +/** + * Raw test data (borrowed from the Emscripten example). + * \n + * See \c testcard.png for the original. + */ +static uint8_t const rawData[] = { +#include "testcard-dxt1.inl" +}; + +#ifndef ZSTD_VERSION_MAJOR +/* + * For the case where the decompression library hasn't been included we add + * dummy functions to fake the process and stop the buffers being optimised out. + */ +size_t ZSTD_compressBound(size_t maxSrc) { + return maxSrc + 32; +} +int ZSTD_maxCLevel(void) { + return 20; +} +size_t ZSTD_compress(void* dst, size_t dstLen, const void* src, size_t srcLen, int level) { + return (memcmp(dst, src, (srcLen < dstLen) ? srcLen : dstLen)) ? level : dstLen; +} +unsigned ZSTD_isError(size_t code) { + return ((int) code) < 0; +} +size_t ZSTD_decompress(void* dst, size_t dstLen, const void* src, size_t srcLen) { + return (memcmp(dst, src, (srcLen < dstLen) ? srcLen : dstLen)) ? 0 : dstLen; +} +#endif + +//*****************************************************************************/ + +/** + * Simple single-file test to compress \c rawData, decompress the result, then + * compare the decompressed version with the original. + */ +int main() { + size_t bounds = ZSTD_compressBound(sizeof rawData); + void* compBuf = malloc(bounds); + void* testBuf = malloc(sizeof rawData); + int compare = -1; + if (compBuf && testBuf) { + size_t compSize = ZSTD_compress(compBuf, bounds, rawData, sizeof rawData, ZSTD_maxCLevel()); + if (!ZSTD_isError(compSize)) { + printf("Compression: PASSED (size: %lu, uncompressed: %lu)\n", (unsigned long) compSize, (unsigned long) (sizeof rawData)); + size_t decSize = ZSTD_decompress(testBuf, sizeof rawData, compBuf, compSize); + if (!ZSTD_isError(decSize)) { + printf("Decompression: PASSED\n"); + compare = memcmp(rawData, testBuf, decSize); + printf("Byte comparison: %s\n", (compare == 0) ? "PASSED" : "FAILED"); + } else { + printf("Decompression: FAILED\n"); + } + } else { + printf("Compression: FAILED\n"); + } + free(compBuf); + free(testBuf); + } + return (compare == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/contrib/single_file_decoder/examples/simple.c b/contrib/single_file_decoder/examples/simple.c index 5646e5f2006..ee63416a6e5 100644 --- a/contrib/single_file_decoder/examples/simple.c +++ b/contrib/single_file_decoder/examples/simple.c @@ -26,2737 +26,7 @@ * See \c testcard.png for the original. */ static uint8_t const rawDxt1[] = { - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0xb5, - 0xde, 0xf7, 0x30, 0x84, 0x00, 0x15, 0x35, 0x20, 0xdf, 0xff, 0x30, 0x84, - 0x00, 0xd4, 0x80, 0x54, 0xde, 0xf7, 0x30, 0x84, 0x00, 0x2b, 0x7e, 0x55, - 0xde, 0xf7, 0x10, 0x84, 0x00, 0xa0, 0x55, 0x55, 0xdf, 0xff, 0xe7, 0x39, - 0x00, 0x2a, 0x3f, 0x3f, 0x82, 0x10, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0xff, 0xff, 0x28, 0x42, 0x00, 0xff, 0xff, 0xff, 0x41, 0x08, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x3f, 0x3f, 0x3f, - 0xff, 0xff, 0x08, 0x42, 0x00, 0xa8, 0xfc, 0xfc, 0xde, 0xf7, 0x30, 0x84, - 0x00, 0x02, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, 0x00, 0xfa, 0xaf, 0x55, - 0xdf, 0xff, 0x30, 0x84, 0x00, 0x15, 0x20, 0x35, 0xde, 0xf7, 0x30, 0x84, - 0x00, 0x54, 0x54, 0x80, 0xff, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x57, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x10, 0x84, 0x15, 0x15, 0x15, 0x2d, 0xff, 0xff, 0x30, 0x84, - 0x54, 0xd4, 0x88, 0x5c, 0xff, 0xff, 0x10, 0x84, 0xb5, 0xe2, 0x57, 0x55, - 0x7d, 0xef, 0x30, 0x84, 0xe0, 0x55, 0x55, 0x55, 0x41, 0x08, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x30, 0x84, 0xd4, 0x54, 0x54, 0x54, - 0x9d, 0xef, 0x30, 0x84, 0x82, 0xd5, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, - 0x57, 0xe2, 0xb5, 0x55, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x38, 0x2d, - 0xff, 0xff, 0x10, 0x84, 0x54, 0x54, 0x54, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x41, 0x08, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0x9e, 0xf7, 0x10, 0x84, 0x55, 0x55, 0x35, 0xe2, - 0x5c, 0xe7, 0x10, 0x84, 0xb5, 0x83, 0x5c, 0x55, 0xff, 0xff, 0x30, 0x84, - 0x38, 0x15, 0x15, 0x15, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xf7, 0x30, 0x84, - 0x88, 0x94, 0x54, 0x54, 0x5c, 0xe7, 0x10, 0x84, 0x57, 0x70, 0x0d, 0xd5, - 0xbe, 0xf7, 0x30, 0x84, 0x55, 0x55, 0x57, 0x62, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x08, 0x42, - 0x3f, 0x3f, 0x2f, 0x00, 0x51, 0x8c, 0xdf, 0xff, 0x61, 0x25, 0x01, 0x55, - 0xff, 0xff, 0x49, 0x4a, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x69, 0x4a, - 0x2f, 0xff, 0xff, 0x00, 0x51, 0x8c, 0xff, 0xff, 0x42, 0x66, 0x60, 0x55, - 0xff, 0xff, 0x28, 0x42, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0xde, 0xf7, 0x10, 0x84, 0x00, 0x55, 0xd5, 0x25, 0xbe, 0xf7, 0x30, 0x84, - 0x00, 0xc9, 0x58, 0x57, 0xff, 0xff, 0x08, 0x42, 0x00, 0x3f, 0x3f, 0x3f, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, - 0x00, 0xbc, 0xfc, 0xfc, 0xbe, 0xf7, 0x10, 0x84, 0x00, 0x58, 0xc9, 0x35, - 0xff, 0xff, 0x10, 0x84, 0x00, 0x55, 0x55, 0x56, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, - 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, - 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, - 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0xe9, 0x93, 0xc7, 0x8b, 0xaa, 0xaa, 0xaa, 0x2a, - 0xbe, 0xf7, 0x10, 0x84, 0x54, 0x94, 0x8c, 0x70, 0x7d, 0xef, 0x10, 0x84, - 0x63, 0x5c, 0x55, 0x55, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0x71, 0x8c, 0xcf, 0x7b, 0xbf, 0xff, 0xff, 0xff, 0x9d, 0xef, 0x10, 0x84, - 0x72, 0x8d, 0x95, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x15, 0x15, 0x1c, 0x23, - 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, - 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, - 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0x56, 0xd6, 0xa1, 0x72, 0xff, 0xff, 0xff, 0x3f, - 0x5c, 0xef, 0x2a, 0x94, 0x15, 0x8d, 0x73, 0x54, 0x41, 0x08, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x30, 0x84, 0x25, 0x15, 0x15, 0x15, 0x7c, 0xf7, 0x09, 0x94, - 0x55, 0x5c, 0x73, 0x85, 0x09, 0x94, 0xa7, 0x8b, 0xff, 0xff, 0xff, 0xfe, - 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, - 0xff, 0xff, 0xff, 0xff, 0x7c, 0xf7, 0xc8, 0x8b, 0x55, 0x55, 0xd5, 0x35, - 0x3b, 0xef, 0x09, 0x94, 0x05, 0x61, 0x58, 0x57, 0x2a, 0x9c, 0xc7, 0x8b, - 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xf9, 0xe6, 0x60, 0x6a, 0x3f, 0xff, 0xff, 0xff, - 0x9d, 0xf7, 0x09, 0x94, 0x56, 0x52, 0x49, 0x35, 0xc2, 0x72, 0xce, 0xac, - 0xaa, 0xaa, 0xaa, 0xa9, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x10, 0x84, 0x00, 0x54, 0xd4, 0x34, - 0xde, 0xf7, 0xef, 0x7b, 0x00, 0x73, 0x5c, 0x57, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0xde, 0xf7, 0xef, 0x7b, 0x00, 0x73, 0xcd, 0x35, - 0xff, 0xff, 0x10, 0x84, 0x00, 0x15, 0x15, 0x17, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x5d, 0xf7, 0xef, 0xaa, 0x55, 0x55, 0xd5, 0x35, - 0xde, 0xf7, 0xef, 0x7b, 0xcc, 0x70, 0x5c, 0x54, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x2c, 0x63, 0xd3, 0x9c, 0x6a, 0xaa, 0xaa, 0xaa, 0xde, 0xf7, 0xef, 0x7b, - 0x1c, 0x33, 0x0d, 0x35, 0xd4, 0x62, 0x57, 0x94, 0xaa, 0xaa, 0xaa, 0xa9, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xd8, 0xdd, 0xcb, 0x99, 0xff, 0xff, 0xff, 0x3f, - 0xdb, 0xee, 0x30, 0xb3, 0x85, 0x61, 0x50, 0x54, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x1d, 0xe7, 0xb6, 0x83, 0x54, 0x52, 0x41, 0x85, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x30, 0xb3, 0x0f, 0xb3, 0xff, 0xff, 0xff, 0xbf, - 0x9e, 0xf7, 0x30, 0xb3, 0x35, 0xcd, 0x71, 0x5a, 0xf2, 0xbb, 0xae, 0xaa, - 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, - 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x5e, 0xef, 0x96, 0x7b, - 0x15, 0xd5, 0x55, 0x55, 0x9e, 0xf7, 0xb6, 0x7b, 0x57, 0x5c, 0x53, 0x69, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x7d, 0xf7, 0x2f, 0xb3, 0x95, 0x35, 0xc5, 0x69, 0xdb, 0xee, 0x0f, 0xb3, - 0x54, 0x57, 0x55, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x5e, 0xef, 0xf2, 0x49, 0x8f, 0x3f, 0xbf, 0xff, 0x7e, 0xef, 0x96, 0x7b, - 0x55, 0x57, 0x54, 0x5a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x7d, 0xf7, 0x2f, 0xb3, 0x55, 0x55, 0x95, 0x35, 0x7d, 0xf7, 0x30, 0xb3, - 0x53, 0x5c, 0x56, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x7e, 0xef, 0xb6, 0x83, 0x71, 0x4d, 0xa5, 0x15, - 0x73, 0x5a, 0xb8, 0x9c, 0xaa, 0xaa, 0xaa, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfc, 0xee, 0x70, 0xb3, - 0xc5, 0x49, 0x51, 0x58, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x19, 0xa5, 0xaf, 0x28, 0x2a, 0xaa, 0xaa, 0xaa, 0x1d, 0xe7, 0xd6, 0x83, - 0x54, 0x58, 0x51, 0x49, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x10, 0x84, - 0x15, 0x15, 0x35, 0x00, 0x9e, 0xf7, 0x30, 0xb3, 0x54, 0x57, 0x55, 0x55, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x3d, 0xe7, 0xb6, 0x7b, 0xc5, 0x35, 0x15, 0xd5, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x08, 0x42, - 0x00, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x71, 0x8c, 0x00, 0x11, 0x1b, 0x14, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x1f, 0x62, 0x1e, 0x5a, 0xea, 0xaa, 0xaa, 0xea, - 0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfa, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, - 0x5f, 0x57, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfc, 0x51, 0xba, 0x51, 0xfe, 0xfe, 0xfa, 0xfe, 0xda, 0x51, 0x99, 0x49, - 0xea, 0xea, 0xe8, 0xea, 0xb9, 0x51, 0x98, 0x49, 0x7e, 0x7e, 0x7e, 0x7e, - 0x97, 0x49, 0x76, 0x41, 0xe8, 0xe8, 0xe8, 0xe8, 0x97, 0x49, 0x75, 0x41, - 0x5f, 0x5f, 0x5f, 0x5f, 0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, - 0x53, 0x39, 0x32, 0x39, 0x7e, 0x7e, 0x5e, 0x7e, 0x31, 0x39, 0x10, 0x31, - 0xfa, 0xfa, 0x78, 0x7a, 0x0f, 0x31, 0xcd, 0x28, 0xa0, 0x80, 0x80, 0x80, - 0xee, 0x30, 0xed, 0x28, 0x5e, 0x7e, 0x5e, 0x5e, 0xcc, 0x28, 0xaa, 0x20, - 0xa0, 0xa0, 0xa0, 0xa0, 0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, - 0xaa, 0x20, 0x88, 0x18, 0xfa, 0xfa, 0xfa, 0xfa, 0x88, 0x18, 0x66, 0x18, - 0xe8, 0xe8, 0xe8, 0xe8, 0x87, 0x18, 0x45, 0x10, 0xfa, 0xfa, 0xfa, 0xfa, - 0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, - 0xa8, 0xe8, 0xa8, 0xe8, 0x44, 0x10, 0x22, 0x08, 0x5f, 0x7f, 0x7f, 0x7f, - 0x22, 0x08, 0x01, 0x08, 0xea, 0xfa, 0xfa, 0xea, 0x01, 0x08, 0x00, 0x00, - 0xaa, 0xea, 0xaa, 0xaa, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x51, 0x8c, - 0x00, 0x50, 0x78, 0x44, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x69, 0x4a, 0xbf, 0x3f, 0x2f, 0x8f, - 0xff, 0xff, 0xef, 0x7b, 0x16, 0x17, 0x15, 0x15, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x1f, 0x62, 0x1e, 0x5a, 0xaa, 0xea, 0xaa, 0xea, 0x1f, 0x62, 0xfd, 0x59, - 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, 0x57, 0x57, 0x57, 0x57, - 0xfd, 0x59, 0xdb, 0x51, 0xfa, 0xfa, 0xfa, 0xfa, 0xdb, 0x51, 0xb9, 0x51, - 0xa0, 0xa0, 0xa0, 0x80, 0xba, 0x51, 0xb9, 0x49, 0xe8, 0xe8, 0xe8, 0xe8, - 0xda, 0x51, 0x98, 0x49, 0x5f, 0x7f, 0x7f, 0x5f, 0x97, 0x49, 0x76, 0x41, - 0xe8, 0xe8, 0xe8, 0xe0, 0x97, 0x49, 0x75, 0x41, 0x57, 0x57, 0x5f, 0x5f, - 0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, 0x53, 0x39, 0x32, 0x39, - 0x5c, 0x5e, 0x7e, 0x5e, 0x32, 0x39, 0x0f, 0x31, 0xfa, 0xfa, 0xfa, 0xfa, - 0x0f, 0x31, 0xee, 0x28, 0xe0, 0xe0, 0xa0, 0xa0, 0x10, 0x31, 0xed, 0x28, - 0x5f, 0x5f, 0x5f, 0x5f, 0xcc, 0x28, 0xcb, 0x20, 0xe0, 0xe8, 0xe8, 0xe0, - 0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, 0xa9, 0x20, 0x88, 0x18, - 0xe8, 0xe8, 0xe8, 0xe8, 0x88, 0x18, 0x66, 0x18, 0xe8, 0xe8, 0xe8, 0xe8, - 0x67, 0x18, 0x65, 0x10, 0xfe, 0xfa, 0xfe, 0xfa, 0x66, 0x10, 0x44, 0x10, - 0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, 0xa8, 0xa8, 0xa8, 0xa8, - 0x44, 0x10, 0x22, 0x08, 0x5f, 0x7f, 0x7f, 0x7f, 0x22, 0x08, 0x01, 0x08, - 0xf8, 0xe8, 0xea, 0xea, 0x01, 0x08, 0x00, 0x00, 0xaa, 0xe8, 0xea, 0xe8, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0xe4, 0x34, 0x94, 0xd4, - 0x3c, 0xe7, 0x69, 0x4a, 0xff, 0xff, 0xfe, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x9d, 0xef, 0x30, 0x84, 0x4d, 0x79, 0x51, 0x5a, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x1f, 0x62, 0x1e, 0x5a, - 0xea, 0xea, 0xea, 0xea, 0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfe, 0xfa, 0xfe, - 0x1e, 0x5a, 0xfd, 0x59, 0x57, 0x5f, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, - 0xfa, 0xfa, 0xfa, 0xfa, 0xdb, 0x51, 0xba, 0x51, 0xe0, 0xe0, 0xe0, 0xe0, - 0xba, 0x51, 0xb9, 0x49, 0xe8, 0xe8, 0xe8, 0xe8, 0xda, 0x51, 0x98, 0x49, - 0x5f, 0x5f, 0x5f, 0x5f, 0x97, 0x49, 0x76, 0x41, 0xe8, 0xe0, 0xe8, 0xe0, - 0x97, 0x49, 0x75, 0x41, 0x5f, 0x5f, 0x5f, 0x5f, 0x75, 0x41, 0x32, 0x39, - 0xea, 0xea, 0xea, 0xea, 0x53, 0x39, 0x32, 0x39, 0x7e, 0x7a, 0x7a, 0x7e, - 0x31, 0x39, 0x10, 0x31, 0x78, 0xf8, 0xf8, 0x78, 0x0f, 0x31, 0xee, 0x28, - 0xa0, 0xe0, 0xa0, 0xe0, 0x10, 0x31, 0xed, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, - 0xed, 0x28, 0xaa, 0x20, 0xea, 0xea, 0xea, 0xea, 0xcc, 0x28, 0xaa, 0x20, - 0x5f, 0x5f, 0x5f, 0x5f, 0xaa, 0x20, 0x88, 0x18, 0xfa, 0xfa, 0xfa, 0xfa, - 0x88, 0x18, 0x66, 0x18, 0xe8, 0xe8, 0xe8, 0xe8, 0x67, 0x18, 0x65, 0x10, - 0xfa, 0xfa, 0xf8, 0xfa, 0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, - 0x44, 0x10, 0x22, 0x08, 0xa8, 0xa8, 0xa8, 0xa8, 0x44, 0x10, 0x22, 0x08, - 0x5f, 0x5f, 0x7f, 0x5f, 0x22, 0x08, 0x01, 0x08, 0xea, 0xea, 0xea, 0xe8, - 0x01, 0x08, 0x00, 0x00, 0xea, 0xea, 0xe8, 0xea, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, 0x9e, 0xf7, 0x30, 0x84, - 0x5c, 0x5b, 0x51, 0x69, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0xff, 0xff, 0xef, 0x7b, 0x55, 0xd5, 0x95, 0x00, 0xbe, 0xf7, 0x10, 0x84, - 0x5c, 0x54, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x1f, 0x62, 0x1e, 0x5a, 0xea, 0xaa, 0xea, 0xea, - 0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, - 0x57, 0x57, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, 0xea, 0xfa, 0xfa, 0xea, - 0xdb, 0x51, 0xb9, 0x51, 0x80, 0x80, 0xa0, 0x80, 0xba, 0x51, 0xb8, 0x49, - 0xa8, 0xa8, 0xa8, 0xa0, 0xb9, 0x51, 0x98, 0x49, 0x7e, 0x7e, 0x7e, 0x7e, - 0x97, 0x49, 0x76, 0x41, 0xa8, 0xe8, 0xe8, 0xe0, 0x97, 0x49, 0x75, 0x41, - 0x5f, 0x5f, 0x57, 0x5f, 0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, - 0x53, 0x39, 0x32, 0x39, 0x58, 0x7e, 0x7a, 0x7a, 0x32, 0x39, 0x0f, 0x31, - 0xfa, 0xfa, 0xfa, 0xfa, 0x0f, 0x31, 0xee, 0x28, 0xa0, 0xe0, 0xe0, 0xe0, - 0xef, 0x30, 0xed, 0x28, 0x5e, 0x7f, 0x5e, 0x7f, 0xed, 0x28, 0xaa, 0x20, - 0xea, 0xea, 0xea, 0xea, 0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, - 0xa9, 0x20, 0x88, 0x18, 0xf8, 0xe8, 0xe8, 0xe8, 0x88, 0x18, 0x66, 0x18, - 0xe8, 0xe8, 0xe8, 0xe8, 0x67, 0x18, 0x65, 0x10, 0xfa, 0xfa, 0xfa, 0xfa, - 0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, - 0xa8, 0xa8, 0xa8, 0xe0, 0x44, 0x10, 0x22, 0x08, 0x7f, 0x7f, 0x5f, 0x5f, - 0x22, 0x08, 0x01, 0x08, 0xfa, 0xf8, 0xfa, 0xf8, 0x01, 0x08, 0x00, 0x00, - 0xa8, 0xa8, 0xa8, 0xa8, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x4d, 0xc5, 0xb5, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0xff, 0xff, 0x30, 0x84, - 0x00, 0xe5, 0x45, 0x6d, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x8c, 0xf8, 0x6b, 0xf0, 0xaa, 0xaa, 0xaa, 0xea, 0x8c, 0xf0, 0x6b, 0xf0, - 0xff, 0xdf, 0xff, 0xff, 0x8b, 0xf0, 0x6b, 0xe8, 0x5f, 0x5f, 0x7f, 0x5f, - 0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, - 0xe0, 0xa0, 0xe0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, 0xf8, 0xf8, 0x78, 0xf8, - 0x69, 0xc8, 0x49, 0xb8, 0xa8, 0xe8, 0xe8, 0xe8, 0x69, 0xc0, 0x48, 0xb0, - 0xfa, 0xfa, 0xfa, 0xfe, 0x69, 0xb8, 0x48, 0xa8, 0x5f, 0x5f, 0x5f, 0x5f, - 0x48, 0xa8, 0x47, 0x98, 0x7a, 0xfa, 0xfa, 0xfa, 0x47, 0x98, 0x47, 0x90, - 0x7c, 0x5c, 0x58, 0x5c, 0x47, 0x90, 0x46, 0x80, 0x7a, 0x7e, 0x7a, 0x7e, - 0x46, 0x80, 0x45, 0x70, 0xf8, 0xf8, 0xf8, 0xf8, 0x45, 0x70, 0x25, 0x68, - 0x78, 0x78, 0x78, 0x78, 0x25, 0x68, 0x24, 0x58, 0xfa, 0xfa, 0xfa, 0xfa, - 0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, - 0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, - 0x23, 0x38, 0x02, 0x28, 0xea, 0xea, 0xea, 0xea, 0x22, 0x30, 0x02, 0x20, - 0xfa, 0xfe, 0xfa, 0xfa, 0x02, 0x20, 0x01, 0x18, 0xe8, 0xe8, 0xe8, 0xf8, - 0x01, 0x18, 0x01, 0x10, 0xf8, 0xf8, 0xf8, 0xe8, 0x01, 0x10, 0x00, 0x08, - 0xe8, 0xe8, 0xe8, 0xe0, 0x01, 0x10, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0xff, 0xff, 0x10, 0x84, 0x00, 0xd5, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, - 0x00, 0x56, 0x54, 0x5e, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0x7d, 0xef, 0x10, 0x84, 0x79, 0x51, 0x53, 0x5a, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0xf8, 0x6b, 0xf0, - 0xe8, 0xa8, 0xe8, 0xa8, 0x8b, 0xf8, 0x6b, 0xe8, 0xea, 0xfa, 0xfa, 0xea, - 0x8b, 0xf0, 0x6b, 0xe8, 0x57, 0x57, 0x57, 0x57, 0x6b, 0xe8, 0x6a, 0xd8, - 0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, 0xa0, 0xa0, 0xa0, 0xe0, - 0x6a, 0xd0, 0x69, 0xc8, 0x60, 0x68, 0xf8, 0xe8, 0x6a, 0xd0, 0x69, 0xc0, - 0x5f, 0x5f, 0x5f, 0x5f, 0x69, 0xc0, 0x48, 0xb0, 0xfa, 0xfa, 0xfa, 0xfa, - 0x68, 0xb0, 0x48, 0xa8, 0x7e, 0x7a, 0x7e, 0x7a, 0x48, 0xa8, 0x47, 0x98, - 0x7a, 0xfa, 0x7a, 0xfa, 0x47, 0x90, 0x47, 0x98, 0x09, 0x09, 0x09, 0x09, - 0x47, 0x90, 0x46, 0x80, 0x7e, 0x7e, 0x7e, 0x7e, 0x46, 0x80, 0x25, 0x70, - 0xe8, 0xe8, 0xe8, 0xf8, 0x46, 0x78, 0x25, 0x68, 0x7e, 0x7e, 0x7e, 0x7e, - 0x45, 0x68, 0x24, 0x58, 0xfa, 0xfe, 0xfa, 0xfa, 0x24, 0x58, 0x24, 0x50, - 0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, 0xfa, 0xfa, 0xfa, 0xfa, - 0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, 0x23, 0x38, 0x02, 0x28, - 0xea, 0xea, 0xfa, 0xea, 0x02, 0x30, 0x22, 0x20, 0xfe, 0xfe, 0xfa, 0xfa, - 0x22, 0x28, 0x01, 0x18, 0x7e, 0x7e, 0xfe, 0xfe, 0x01, 0x18, 0x01, 0x10, - 0xe8, 0xe8, 0xe8, 0xe8, 0x01, 0x10, 0x00, 0x08, 0xe8, 0xe8, 0xe8, 0xe0, - 0x01, 0x08, 0x00, 0x08, 0xff, 0xff, 0xfb, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x10, 0x84, 0x5b, 0x51, 0x71, 0x69, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xdf, 0xff, 0x10, 0x84, 0x54, 0x54, 0xd4, 0x94, - 0x1c, 0xe7, 0xef, 0x7b, 0x5c, 0x54, 0x54, 0x56, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x8c, 0xf8, 0x6b, 0xf0, 0xfa, 0xea, 0xea, 0xea, - 0x8c, 0xf0, 0x6b, 0xf0, 0xfa, 0xfe, 0xfa, 0xff, 0x8b, 0xf0, 0x6b, 0xe8, - 0x5f, 0x5f, 0x5e, 0x5f, 0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, - 0x6a, 0xd8, 0x6a, 0xd0, 0xe0, 0xa0, 0xa0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, - 0xf8, 0xe8, 0xf8, 0xf8, 0x6a, 0xc8, 0x69, 0xc0, 0x7e, 0x7e, 0x5e, 0x5e, - 0x69, 0xc0, 0x48, 0xb0, 0xfa, 0xfa, 0xfa, 0xfa, 0x68, 0xb0, 0x48, 0xa8, - 0x7e, 0x5e, 0x7a, 0x7e, 0x48, 0xa8, 0x47, 0x98, 0x7a, 0x7a, 0x7a, 0xfa, - 0x47, 0x90, 0x47, 0x98, 0x09, 0x09, 0x09, 0x09, 0x47, 0x90, 0x46, 0x80, - 0x7e, 0x7e, 0x7a, 0x7e, 0x46, 0x80, 0x25, 0x70, 0xfa, 0xea, 0xea, 0xea, - 0x46, 0x78, 0x25, 0x68, 0x7e, 0x7e, 0x7e, 0x7e, 0x45, 0x68, 0x24, 0x58, - 0xfe, 0xfa, 0xfe, 0xfe, 0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, - 0x24, 0x50, 0x23, 0x40, 0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, - 0x78, 0x78, 0x78, 0x78, 0x23, 0x38, 0x22, 0x28, 0xea, 0xfa, 0xfa, 0xfa, - 0x22, 0x30, 0x02, 0x20, 0xfa, 0xfe, 0xfa, 0xfa, 0x22, 0x28, 0x01, 0x18, - 0xfe, 0xfe, 0xfe, 0xfe, 0x01, 0x18, 0x01, 0x10, 0xe8, 0xe8, 0xe8, 0xf8, - 0x01, 0x10, 0x00, 0x08, 0xe8, 0xe8, 0xe0, 0xe8, 0x01, 0x10, 0x00, 0x00, - 0xfe, 0xfa, 0xfa, 0xfe, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x7d, 0xef, 0x10, 0x84, 0x4d, 0x45, 0xe5, 0xa5, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xff, 0xff, 0x10, 0x84, 0x94, 0x14, 0xb4, 0x00, 0xdf, 0xff, 0xef, 0x7b, - 0x57, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x8c, 0xf8, 0x6b, 0xf0, 0xea, 0xea, 0xea, 0xea, 0x8c, 0xf0, 0x6b, 0xf0, - 0xff, 0xff, 0xff, 0xfb, 0x6b, 0xf0, 0x6b, 0xe0, 0xea, 0xfa, 0xea, 0xfa, - 0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, - 0xe0, 0xe0, 0xa0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, 0x70, 0xe8, 0x78, 0xe8, - 0x6a, 0xd0, 0x69, 0xc0, 0x5f, 0x5f, 0x5f, 0x5f, 0x69, 0xc0, 0x48, 0xb0, - 0xfe, 0xfe, 0xfa, 0x7a, 0x68, 0xb0, 0x48, 0xa8, 0x7a, 0x7a, 0x7e, 0x7a, - 0x48, 0xa8, 0x47, 0x98, 0xfa, 0xfa, 0xfa, 0xfa, 0x47, 0x90, 0x47, 0x98, - 0x09, 0x09, 0x09, 0x09, 0x47, 0x90, 0x46, 0x80, 0x7a, 0x7a, 0x7e, 0x7e, - 0x46, 0x80, 0x25, 0x70, 0xe8, 0xe8, 0xe8, 0xe8, 0x45, 0x70, 0x25, 0x68, - 0x78, 0x78, 0x78, 0x78, 0x25, 0x68, 0x24, 0x58, 0xfa, 0xfa, 0xfa, 0xfa, - 0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, - 0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, - 0x23, 0x38, 0x02, 0x28, 0xea, 0xfa, 0xea, 0xea, 0x22, 0x30, 0x02, 0x20, - 0xfa, 0xfa, 0xfa, 0xfe, 0x22, 0x28, 0x01, 0x18, 0xfe, 0xfe, 0xfe, 0x7e, - 0x01, 0x18, 0x01, 0x10, 0xe8, 0xe8, 0xf8, 0xe8, 0x01, 0x10, 0x00, 0x08, - 0xa8, 0xe8, 0xa0, 0xa8, 0x01, 0x10, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x10, 0x84, - 0xb5, 0x15, 0x95, 0x00, 0xff, 0xff, 0x10, 0x84, 0x15, 0x15, 0x17, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, - 0x00, 0x44, 0x44, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x41, 0x08, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0xbe, 0xf7, 0x10, 0x84, 0x00, 0x14, 0x14, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x6c, 0x78, 0x78, 0x50, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x30, 0x84, - 0x1e, 0x1b, 0x1b, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdf, 0xff, 0x10, 0x84, 0x50, 0x50, 0x58, 0x58, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x30, 0x84, 0x11, 0x11, 0x39, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x42, - 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0xff, 0xff, 0x08, 0x42, 0x2b, 0x2b, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xa2, 0x10, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x04, 0x21, 0xbe, 0xf7, - 0x55, 0x5a, 0x5a, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xff, 0xff, 0x28, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x49, 0x4a, 0x0f, 0x0f, 0x0f, 0x0f, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0x28, 0x42, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x10, 0x84, 0xdf, 0xff, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xa2, 0x10, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xbe, 0xf7, 0xaa, 0x52, - 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x08, 0x42, 0x00, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x08, 0x42, 0x00, 0x2b, 0x2b, 0x2b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0x10, 0x84, - 0x58, 0x58, 0x50, 0x50, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x30, 0x84, 0x39, 0x39, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x50, 0x78, 0x78, 0x6c, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x30, 0x84, - 0x11, 0x1b, 0x1b, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xbe, 0xf7, 0x30, 0x84, 0x4c, 0x44, 0x44, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x41, 0x08, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x1c, 0x14, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, - 0x00, 0xb4, 0x14, 0x94, 0xdf, 0xff, 0xef, 0x7b, 0x00, 0x55, 0x55, 0x57, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x10, 0x84, 0x00, 0x95, 0x15, 0xb5, - 0xff, 0xff, 0x10, 0x84, 0x00, 0x17, 0x15, 0x15, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xdf, 0xff, 0x10, 0x84, 0x94, 0xd4, 0x54, 0x54, - 0x3c, 0xe7, 0xef, 0x7b, 0x56, 0x54, 0x54, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x7d, 0xef, 0x10, 0x84, 0xa5, 0xe5, 0x45, 0x4d, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0x5d, 0xef, 0x10, 0x84, - 0x5a, 0x53, 0x51, 0x79, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x10, 0x84, - 0x69, 0x71, 0x51, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x30, 0x84, 0x6d, 0x45, 0xe5, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, - 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x10, 0x84, - 0x55, 0x55, 0xd5, 0x00, 0xff, 0xff, 0x10, 0x84, 0x5e, 0x54, 0x56, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0xff, 0xff, 0xef, 0x7b, 0x00, 0x95, 0xd5, 0x55, 0xbe, 0xf7, 0x10, 0x84, - 0x00, 0x57, 0x54, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0xbe, 0xf7, 0x10, 0x84, 0x00, 0xb5, 0xc5, 0x4d, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x30, 0x84, 0x5a, 0x51, 0x79, 0x4d, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, - 0x9e, 0xf7, 0x30, 0x84, 0x69, 0x51, 0x5b, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x3c, 0xe7, 0x69, 0x4a, 0x8f, 0x2f, 0x3f, 0xbf, 0xff, 0xff, 0xef, 0x7b, - 0x15, 0x15, 0x17, 0x16, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x10, 0x84, 0xd4, 0x94, 0x34, 0xe4, 0x1c, 0xe7, 0x69, 0x4a, - 0xfc, 0xfe, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x08, 0x42, - 0xff, 0xff, 0xff, 0x00, 0xdf, 0xff, 0x71, 0x8c, 0x14, 0x1b, 0x11, 0x00, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x51, 0x8c, - 0x44, 0x78, 0x50, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0xff, 0xff, 0x10, 0x84, 0x00, 0x35, 0x15, 0x15, 0xbe, 0xef, 0xb0, 0x4c, - 0x55, 0x55, 0x57, 0x54, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x5b, 0xe7, 0x29, 0x7c, - 0xd5, 0x15, 0x35, 0xc5, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x9d, 0xe7, 0xd0, 0x54, 0x5a, 0x51, 0x69, 0xc5, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x52, 0x70, 0xa5, - 0xaa, 0xaa, 0xaa, 0x6a, 0x3a, 0xe7, 0x6a, 0x84, 0x49, 0x51, 0x58, 0x54, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x9d, 0xef, 0xb0, 0x4c, 0x35, 0x95, 0x55, 0x55, 0x9d, 0xef, 0xd0, 0x4c, - 0x55, 0x56, 0x5c, 0x53, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x9d, 0xef, 0x49, 0x84, 0x15, 0xa5, 0x4d, 0x71, - 0x2e, 0x9d, 0xa6, 0x6b, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x9d, 0xe7, 0xb0, 0x4c, 0x69, 0xc5, 0x35, 0x95, - 0x3c, 0xd7, 0xaf, 0x4c, 0x55, 0x55, 0x57, 0x54, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x7c, 0xef, 0xc0, 0x4a, 0xff, 0xbf, 0x3f, 0x8f, - 0x9c, 0xef, 0x29, 0x7c, 0x5a, 0x54, 0x57, 0x55, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xb0, 0x4c, 0xb0, 0x44, 0x2a, 0xaa, 0xaa, 0xaa, 0xbe, 0xef, 0xb0, 0x4c, - 0x5a, 0x71, 0xcd, 0x35, 0x6e, 0x3c, 0xf1, 0x5c, 0xaa, 0xaa, 0xaa, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x7c, 0xef, 0x29, 0x7c, 0x55, 0x55, 0xd5, 0x15, - 0xbd, 0xf7, 0x49, 0x7c, 0x69, 0x53, 0x5c, 0x57, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x7d, 0xe7, 0xb0, 0x4c, 0x95, 0x55, 0x55, 0x55, - 0x3b, 0xd7, 0xd0, 0x4c, 0x54, 0x50, 0x61, 0x85, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x3a, 0xe7, 0x49, 0x84, 0x85, 0x41, 0x52, 0x54, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xe7, 0x8f, 0x44, - 0x35, 0xd5, 0x55, 0x55, 0xde, 0xf7, 0xef, 0x7b, 0x54, 0x5c, 0x70, 0xcc, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x2c, 0x63, 0xd3, 0x9c, 0xaa, 0xaa, 0xaa, 0x6a, - 0xde, 0xf7, 0xef, 0x7b, 0x35, 0x0d, 0x33, 0x1c, 0x70, 0xad, 0x85, 0x63, - 0xfe, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x10, 0x84, 0x34, 0xd4, 0x54, 0x00, 0xde, 0xf7, 0xef, 0x7b, - 0x57, 0x5c, 0x73, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, - 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0xde, 0xf7, 0xef, 0x7b, 0x35, 0xcd, 0x73, 0x00, 0xff, 0xff, 0x10, 0x84, - 0x17, 0x15, 0x15, 0x00, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x7e, 0xef, 0xd6, 0x63, 0x35, 0xd5, 0x55, 0x55, - 0x3d, 0xe7, 0x17, 0x6c, 0x57, 0x58, 0x61, 0x05, 0xd8, 0x8c, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x57, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0xfd, 0xde, 0x93, 0x32, 0xff, 0xff, 0xff, 0x3f, - 0x9e, 0xef, 0x37, 0x6c, 0x35, 0x49, 0x52, 0x56, 0xf6, 0x63, 0xfb, 0xb5, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x9e, 0xef, 0xf6, 0x63, - 0x95, 0x55, 0x55, 0x55, 0x5e, 0xe7, 0x16, 0x6c, 0x5c, 0x73, 0x8d, 0x15, - 0x41, 0x08, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x15, 0x25, - 0x9e, 0xef, 0x36, 0x6c, 0x85, 0x73, 0x5c, 0x55, 0x16, 0x6c, 0xf6, 0x63, - 0x57, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x16, 0x6c, 0xf6, 0x63, 0xd5, 0x55, 0x55, 0x55, 0xbe, 0xf7, 0x10, 0x84, - 0x70, 0x8c, 0x94, 0x54, 0x7d, 0xef, 0x10, 0x84, 0x55, 0x55, 0x5c, 0x63, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0x71, 0x8c, 0xcf, 0x7b, - 0xff, 0xff, 0xff, 0xbf, 0x9d, 0xef, 0x10, 0x84, 0x55, 0x95, 0x8d, 0x72, - 0xbe, 0xf7, 0x10, 0x84, 0x23, 0x1c, 0x15, 0x15, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0xde, 0xf7, 0x10, 0x84, 0x25, 0xd5, 0x55, 0x00, 0xbe, 0xf7, 0x30, 0x84, - 0x57, 0x58, 0xc9, 0x00, 0xff, 0xff, 0x08, 0x42, 0x3f, 0x3f, 0x3f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x08, 0x42, - 0xfc, 0xfc, 0xbc, 0x00, 0xbe, 0xf7, 0x10, 0x84, 0x35, 0xc9, 0x58, 0x00, - 0xff, 0xff, 0x10, 0x84, 0x56, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, - 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0xff, 0xff, 0x08, 0x42, 0x00, 0x2f, 0x3f, 0x3f, 0xff, 0xff, 0x8a, 0x52, - 0x00, 0xfc, 0xe0, 0x2c, 0xdf, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x56, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0xdf, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x25, 0xff, 0xff, 0x8a, 0x52, - 0x00, 0x2f, 0x22, 0x3e, 0xff, 0xff, 0x08, 0x42, 0x00, 0xfc, 0xfc, 0xfc, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, - 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, - 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x41, 0x08, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0x9e, 0xf7, 0x10, 0x84, 0xe2, 0x35, 0x55, 0x55, 0x3c, 0xe7, 0x10, 0x84, - 0x55, 0x5c, 0x83, 0xb5, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x15, 0x38, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xf7, 0x30, 0x84, 0x54, 0x54, 0x94, 0x88, - 0x5c, 0xe7, 0x10, 0x84, 0xd5, 0x0d, 0x70, 0x57, 0xbe, 0xf7, 0x30, 0x84, - 0x62, 0x57, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x10, 0x84, 0x2d, 0x15, 0x15, 0x15, 0xff, 0xff, 0x30, 0x84, - 0x5c, 0x88, 0xd4, 0x54, 0xff, 0xff, 0x10, 0x84, 0x55, 0x57, 0xe2, 0xb5, - 0x9d, 0xef, 0x30, 0x84, 0x55, 0x55, 0x55, 0xe0, 0x41, 0x08, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x30, 0x84, 0x54, 0x54, 0x54, 0xd4, - 0x9d, 0xef, 0x30, 0x84, 0x55, 0x55, 0xd5, 0x82, 0xff, 0xff, 0x10, 0x84, - 0x55, 0xb5, 0xe2, 0x57, 0xff, 0xff, 0x30, 0x84, 0x2d, 0x38, 0x15, 0x15, - 0xff, 0xff, 0x10, 0x84, 0x5c, 0x54, 0x54, 0x54, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, - 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x30, 0x84, - 0xb5, 0x55, 0x55, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x20, 0x35, 0x15, 0x00, - 0xdf, 0xff, 0x30, 0x84, 0x54, 0x80, 0xd4, 0x00, 0xde, 0xf7, 0x30, 0x84, - 0x55, 0x7e, 0x2b, 0x00, 0xdf, 0xff, 0x10, 0x84, 0x55, 0x55, 0xa0, 0x00, - 0xef, 0x7b, 0xdf, 0xff, 0x40, 0x40, 0x6a, 0x55, 0x82, 0x10, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x28, 0x42, 0xff, 0xff, 0xff, 0x00, - 0x21, 0x08, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xc3, 0x18, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xa8, 0x00, - 0xde, 0xf7, 0x30, 0x84, 0x55, 0x55, 0x02, 0x00, 0xff, 0xff, 0x10, 0x84, - 0x55, 0xaf, 0xfa, 0x00, 0xdf, 0xff, 0x30, 0x84, 0x35, 0x20, 0x15, 0x00, - 0xde, 0xf7, 0x30, 0x84, 0x80, 0x54, 0x54, 0x00, 0xff, 0xff, 0x30, 0x84, - 0x57, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, - 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, - 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55 +#include "testcard-dxt1.inl" }; /** @@ -2765,267 +35,7 @@ static uint8_t const rawDxt1[] = { * See \c testcard.png for the original. */ static uint8_t const srcZstd[] = { - 0x28, 0xb5, 0x2f, 0xfd, 0x60, 0x00, 0x7f, 0x6d, 0x61, 0x00, 0x0a, 0x66, - 0xec, 0x17, 0x48, 0x60, 0x1c, 0x5a, 0xc9, 0x5d, 0x1a, 0x38, 0x07, 0xe8, - 0xc5, 0x82, 0x99, 0x68, 0xe6, 0x95, 0x45, 0x58, 0x0d, 0x0c, 0xf3, 0x36, - 0xc8, 0xd9, 0x0f, 0x46, 0x2d, 0x68, 0x11, 0xf8, 0x31, 0x10, 0xa1, 0x1a, - 0x2f, 0x99, 0x5c, 0x84, 0xfd, 0x92, 0x02, 0xe6, 0x3b, 0x44, 0x9b, 0x01, - 0x5d, 0x92, 0xff, 0x38, 0x26, 0x00, 0x6a, 0x6b, 0xc3, 0x53, 0xb2, 0x0c, - 0x25, 0xf3, 0xd8, 0x59, 0x68, 0x9b, 0x14, 0x8a, 0x89, 0x75, 0x18, 0x03, - 0x1d, 0xc9, 0x0f, 0x63, 0x01, 0x73, 0x01, 0x72, 0x01, 0x4f, 0x66, 0x31, - 0x58, 0x0f, 0x97, 0x4b, 0x0c, 0x4c, 0x06, 0xac, 0x07, 0x0b, 0x68, 0xd4, - 0xad, 0x80, 0x64, 0x13, 0x74, 0xa1, 0x12, 0x16, 0x58, 0xcf, 0x1a, 0x95, - 0x5f, 0x0d, 0x26, 0x55, 0xd0, 0x9c, 0xf4, 0x52, 0x35, 0x2e, 0x20, 0xc1, - 0x06, 0x69, 0x03, 0x0a, 0x93, 0x83, 0x5e, 0x27, 0x9b, 0x4c, 0x6d, 0xee, - 0x87, 0x03, 0x30, 0x6c, 0x46, 0xd7, 0x50, 0x5c, 0xca, 0xe6, 0xa6, 0x4d, - 0xa8, 0xf6, 0xab, 0xd7, 0x0e, 0x27, 0x27, 0x90, 0xc4, 0xb2, 0xd1, 0x10, - 0xfa, 0x43, 0x82, 0xc8, 0xf2, 0xe5, 0xff, 0xff, 0xd5, 0x52, 0x62, 0x43, - 0x87, 0x26, 0x2a, 0x05, 0x70, 0x0e, 0xb0, 0x2f, 0xc4, 0x56, 0xef, 0xb5, - 0xca, 0xb8, 0x53, 0xb7, 0x96, 0x0e, 0xe7, 0x00, 0x2c, 0xa8, 0xda, 0x3b, - 0x07, 0x70, 0xa7, 0x78, 0x38, 0x60, 0x87, 0x7a, 0x01, 0x3b, 0x75, 0xec, - 0xfa, 0x77, 0xe2, 0x46, 0x94, 0x61, 0x8e, 0x0d, 0x0c, 0xfb, 0xe7, 0x8b, - 0x13, 0x50, 0x31, 0xa9, 0x27, 0xcd, 0x27, 0xef, 0x6b, 0xa6, 0xab, 0x9c, - 0x4d, 0x95, 0x6c, 0x3a, 0xbb, 0x8e, 0x96, 0x92, 0x18, 0x5a, 0x7c, 0x4f, - 0xff, 0x7b, 0x38, 0xf2, 0xdb, 0x86, 0xde, 0xff, 0x1f, 0x2f, 0x21, 0x86, - 0x7d, 0xbf, 0x45, 0xd0, 0x6e, 0x77, 0x0a, 0xee, 0x0a, 0xee, 0x14, 0x9a, - 0xb8, 0x84, 0xf3, 0xac, 0xbe, 0xc8, 0x7f, 0x8d, 0xff, 0xff, 0xcf, 0x2a, - 0xfb, 0x69, 0xfc, 0xfb, 0xfd, 0x7a, 0x10, 0x22, 0x36, 0xfc, 0xff, 0x3f, - 0xcf, 0xd0, 0xf1, 0x7f, 0xfe, 0xff, 0x3d, 0x24, 0xdf, 0x78, 0x4a, 0xff, - 0xda, 0x9c, 0x39, 0xcf, 0xef, 0xe7, 0xfd, 0x52, 0x98, 0xb5, 0x40, 0x92, - 0xee, 0xdd, 0x99, 0xf5, 0x53, 0x5b, 0x65, 0x6b, 0xb5, 0xd8, 0x7b, 0xae, - 0xfa, 0xc1, 0x0f, 0x0c, 0x7f, 0x4f, 0x55, 0xa3, 0xad, 0x2c, 0xa0, 0xbd, - 0xf7, 0x2a, 0x0e, 0xe8, 0xbd, 0xc7, 0x5e, 0xf5, 0xd8, 0x54, 0x9e, 0x56, - 0xa3, 0xd6, 0x59, 0xd5, 0xfe, 0x1f, 0xc0, 0x30, 0x8c, 0xfc, 0x46, 0x04, - 0xae, 0x60, 0xbc, 0xe8, 0xcf, 0xec, 0x3d, 0xde, 0xf9, 0xf0, 0xfe, 0xef, - 0x7d, 0xcc, 0xf7, 0x2b, 0xe5, 0x1b, 0x70, 0xff, 0xff, 0x7e, 0x3f, 0x6e, - 0xe4, 0x02, 0x07, 0xfc, 0x1b, 0x7a, 0xff, 0xe7, 0x58, 0xfc, 0x7e, 0x3a, - 0xdc, 0x97, 0xfd, 0x57, 0xef, 0xa3, 0xfc, 0x2a, 0xc7, 0x4d, 0xf3, 0xcb, - 0x9d, 0xce, 0xac, 0xfe, 0xeb, 0x2e, 0x86, 0xb9, 0x69, 0x54, 0xef, 0xf9, - 0x55, 0xcf, 0xff, 0x48, 0x24, 0x72, 0x3a, 0x9d, 0x72, 0x2f, 0x2f, 0x2f, - 0xff, 0x3f, 0xe7, 0x01, 0x6c, 0x4d, 0x6c, 0xcd, 0x2d, 0x5b, 0x53, 0xb7, - 0x59, 0x22, 0x08, 0x0b, 0xa7, 0x92, 0x15, 0x75, 0x93, 0xb0, 0x5d, 0xaf, - 0x2a, 0x63, 0x95, 0x1d, 0x25, 0xd2, 0xd2, 0xa8, 0x1c, 0x84, 0xc9, 0xdc, - 0x72, 0xba, 0xd7, 0xfc, 0x69, 0xf5, 0xc7, 0x19, 0xa9, 0xbe, 0xfa, 0x26, - 0x55, 0x25, 0x75, 0xb7, 0x60, 0xa3, 0xd8, 0x68, 0x54, 0xb7, 0x1b, 0xa5, - 0x54, 0x62, 0xb1, 0x49, 0xde, 0xe2, 0xac, 0xa2, 0xe8, 0x7b, 0xff, 0x5f, - 0x75, 0x4e, 0xb8, 0xa2, 0xdd, 0x6a, 0xb7, 0xda, 0x6e, 0x2e, 0x04, 0xcd, - 0x08, 0x2f, 0xec, 0x8e, 0x49, 0xaf, 0x49, 0x6f, 0x8b, 0x4f, 0x2e, 0x1a, - 0xc5, 0x62, 0x7b, 0x6b, 0x3e, 0x32, 0x3e, 0x32, 0xbe, 0x08, 0x35, 0x4d, - 0x63, 0x93, 0xa6, 0xc8, 0x42, 0xe6, 0x21, 0xcc, 0x59, 0xc8, 0x4c, 0xe5, - 0x86, 0xe1, 0x03, 0x06, 0xa4, 0xec, 0xff, 0xb7, 0x78, 0x7e, 0x62, 0x43, - 0xc7, 0x2c, 0x50, 0x30, 0x4a, 0xc8, 0x9b, 0xf3, 0xbf, 0xe6, 0x62, 0xa0, - 0x50, 0xa6, 0x9c, 0xe3, 0x6e, 0x5b, 0xaf, 0x77, 0x8b, 0xbb, 0xe1, 0x70, - 0xaa, 0xaa, 0xaa, 0x92, 0xb4, 0x52, 0xad, 0x14, 0x87, 0x93, 0x0b, 0xe6, - 0x82, 0x39, 0x11, 0xb9, 0x20, 0x9a, 0x16, 0x34, 0x22, 0x68, 0xb2, 0x68, - 0xb2, 0x76, 0xd3, 0xe8, 0x6e, 0xda, 0x6b, 0x62, 0x34, 0x2e, 0x8d, 0xbd, - 0x2d, 0x3d, 0x6b, 0x4c, 0x26, 0x33, 0xda, 0x33, 0xf3, 0x91, 0x51, 0x46, - 0x79, 0xbd, 0x3e, 0x39, 0x9f, 0xcf, 0xd2, 0xb8, 0x5c, 0xfa, 0x22, 0xf8, - 0x8e, 0xb6, 0xbe, 0x08, 0x40, 0x14, 0x49, 0x40, 0x14, 0xf2, 0x0c, 0x2d, - 0x30, 0x85, 0x3c, 0x63, 0x29, 0xd3, 0x98, 0x85, 0x6c, 0xb5, 0xdb, 0xad, - 0x5c, 0x63, 0x9e, 0x72, 0xcf, 0x43, 0xe6, 0xaf, 0x77, 0xa6, 0xe2, 0x21, - 0x0c, 0x4d, 0xd3, 0x49, 0x1e, 0xc2, 0x14, 0x6f, 0xee, 0xdb, 0x7b, 0x7b, - 0x08, 0xb3, 0xa4, 0x60, 0x3b, 0x9d, 0x6e, 0x8b, 0x37, 0x4b, 0x0a, 0x74, - 0x35, 0x33, 0xbc, 0xf9, 0x64, 0x85, 0x63, 0x32, 0x29, 0x20, 0x59, 0x0c, - 0x3c, 0x96, 0x67, 0x62, 0xb7, 0x8a, 0x92, 0x4d, 0xa0, 0xd3, 0xf3, 0xd1, - 0x85, 0x80, 0x38, 0xcb, 0x64, 0x60, 0xc9, 0xb5, 0xaf, 0x97, 0x8d, 0x20, - 0x45, 0x28, 0xb8, 0xab, 0xe8, 0xc9, 0x0a, 0x88, 0x1f, 0xd6, 0x47, 0x54, - 0xf1, 0xd3, 0xfb, 0x62, 0xa7, 0xfd, 0xf2, 0x8b, 0xfd, 0xb6, 0xe4, 0x2e, - 0xb6, 0x91, 0x73, 0x1c, 0xd0, 0x7b, 0xba, 0x83, 0xc9, 0xac, 0x51, 0x39, - 0x92, 0xc5, 0x4f, 0x30, 0x1e, 0x2e, 0xd5, 0xf1, 0xa8, 0xa6, 0xa5, 0x80, - 0x70, 0xb9, 0xbc, 0xb7, 0xc2, 0x52, 0x32, 0x6c, 0xe3, 0x3d, 0xed, 0x41, - 0xa4, 0x4b, 0x31, 0x2a, 0xe6, 0x62, 0x11, 0x19, 0x95, 0x73, 0x1d, 0xbf, - 0xe1, 0x6c, 0xfc, 0x47, 0x75, 0x6c, 0x37, 0x63, 0x02, 0xf8, 0x34, 0x40, - 0x9a, 0x00, 0x1d, 0xf7, 0x32, 0x56, 0x77, 0xda, 0x5b, 0x9f, 0x9f, 0x0f, - 0xbb, 0x91, 0x5b, 0xbd, 0xe7, 0x58, 0x82, 0x4a, 0x20, 0xcd, 0x4f, 0x47, - 0x15, 0xf3, 0x51, 0xf1, 0x43, 0x51, 0x10, 0x96, 0xae, 0xba, 0xf7, 0x21, - 0x50, 0xef, 0x55, 0x27, 0x0c, 0x1f, 0xe0, 0x54, 0xf8, 0xc9, 0x69, 0xef, - 0xb9, 0x53, 0xf7, 0x83, 0x73, 0x9d, 0xce, 0x86, 0x07, 0x83, 0x44, 0x61, - 0x37, 0x35, 0x35, 0x33, 0x4e, 0x33, 0x33, 0x3e, 0x9f, 0x50, 0x48, 0x24, - 0xe6, 0xd0, 0x79, 0x49, 0xc3, 0x2d, 0xa0, 0x46, 0x31, 0x9a, 0x72, 0xc3, - 0x84, 0xff, 0x7a, 0x95, 0xbb, 0x00, 0x22, 0xcc, 0x14, 0x00, 0x04, 0xac, - 0x60, 0x64, 0x86, 0xe4, 0x6f, 0xb1, 0x58, 0xf4, 0xdc, 0xb0, 0x05, 0x00, - 0x72, 0x38, 0xf8, 0xce, 0xce, 0x8e, 0xcf, 0x37, 0x33, 0x43, 0x24, 0x0a, - 0x85, 0x33, 0x35, 0x35, 0x37, 0xc2, 0xa8, 0x28, 0x27, 0x1b, 0x9d, 0xce, - 0x29, 0x18, 0xe4, 0xfc, 0x09, 0x53, 0xa5, 0x51, 0xad, 0x74, 0x79, 0x7b, - 0xb5, 0x4a, 0x65, 0x94, 0x36, 0x89, 0xf5, 0x62, 0x9b, 0xd8, 0x9a, 0xe8, - 0x2b, 0xff, 0xa1, 0x73, 0xfe, 0x2e, 0x2c, 0x41, 0x45, 0x37, 0xef, 0x6e, - 0x7b, 0x38, 0xca, 0xa5, 0xd2, 0xb8, 0x1c, 0x3b, 0x96, 0x21, 0xbb, 0x5d, - 0xad, 0xd1, 0xdb, 0x1c, 0xf6, 0x5e, 0x4b, 0xd9, 0x59, 0x1b, 0x67, 0xf5, - 0x7a, 0x7c, 0x9a, 0x91, 0x3e, 0x8e, 0xe3, 0xee, 0x7b, 0xb9, 0xa4, 0xb9, - 0xf5, 0x70, 0xee, 0x1d, 0x4e, 0x4f, 0xcc, 0xd6, 0x7b, 0x07, 0x71, 0x48, - 0xf2, 0x06, 0xd0, 0x10, 0x82, 0x21, 0xe4, 0x55, 0x2e, 0xa5, 0x1d, 0xbe, - 0x48, 0x8c, 0x69, 0xbb, 0x24, 0x40, 0x68, 0x9b, 0xba, 0x5a, 0x5a, 0xa7, - 0xe2, 0xd1, 0xac, 0xc2, 0xd8, 0x87, 0x9c, 0xe3, 0x78, 0xee, 0xa6, 0xcd, - 0xdd, 0x68, 0x6e, 0xdd, 0xdb, 0x2e, 0xc6, 0xbb, 0x8b, 0xe9, 0xc1, 0xd9, - 0xf6, 0x62, 0x7e, 0x72, 0x7e, 0x72, 0x34, 0xe4, 0x68, 0xc8, 0x11, 0x32, - 0x10, 0x32, 0x20, 0x32, 0xf0, 0x12, 0x19, 0x90, 0xe0, 0x45, 0x91, 0xe0, - 0x25, 0x83, 0xba, 0xc9, 0x20, 0x26, 0x87, 0xa5, 0x72, 0xa9, 0x64, 0x72, - 0x80, 0x21, 0x54, 0x13, 0xeb, 0x29, 0x18, 0x42, 0x34, 0x84, 0x94, 0x34, - 0x84, 0xa4, 0x1d, 0xa4, 0x1d, 0x82, 0x1c, 0xef, 0xaf, 0x0e, 0x63, 0x47, - 0x6d, 0x10, 0xb9, 0xec, 0xd8, 0x2d, 0x3b, 0x9e, 0x21, 0xb1, 0x67, 0x48, - 0x34, 0x24, 0x1a, 0x52, 0xdb, 0xa4, 0x6d, 0x62, 0xd3, 0xfa, 0xff, 0xfa, - 0x03, 0x34, 0xef, 0x9d, 0xc9, 0xe1, 0x5d, 0xec, 0xf5, 0xf1, 0x79, 0x8c, - 0x97, 0xd2, 0x24, 0xc1, 0x2d, 0xe0, 0x39, 0x16, 0x1e, 0xa9, 0x41, 0xc3, - 0xbf, 0x4a, 0xd9, 0x3c, 0xea, 0x77, 0x96, 0x55, 0xe6, 0x95, 0xc3, 0xf1, - 0x8e, 0x7b, 0x4f, 0xad, 0x61, 0xf8, 0xe7, 0x01, 0xad, 0x46, 0xf5, 0x2c, - 0xac, 0x55, 0x2c, 0x94, 0xaa, 0x46, 0xfb, 0x5e, 0xcd, 0xaa, 0x1f, 0x78, - 0x4f, 0x2f, 0xd1, 0xc9, 0x02, 0xd6, 0x2c, 0x67, 0xef, 0x3f, 0x54, 0xab, - 0xda, 0x03, 0x79, 0x1f, 0xab, 0xfd, 0x0c, 0x38, 0x3c, 0xbc, 0xe1, 0xd5, - 0x01, 0xf6, 0xfb, 0xfb, 0xf1, 0x70, 0xee, 0xfd, 0x90, 0x13, 0x97, 0xc4, - 0xbc, 0x08, 0xe7, 0x4b, 0x88, 0x34, 0xf7, 0x56, 0x1e, 0x0c, 0xdb, 0xe4, - 0x9c, 0x78, 0xf1, 0xf4, 0x62, 0x4c, 0xb5, 0xf7, 0xdd, 0xd9, 0x4c, 0x5a, - 0x69, 0xa6, 0x36, 0x27, 0x03, 0xbe, 0x86, 0xc2, 0x72, 0xa2, 0x60, 0x73, - 0xf1, 0xe0, 0x17, 0x50, 0xb5, 0x93, 0x81, 0xac, 0xf1, 0xc9, 0xd4, 0x66, - 0x73, 0x71, 0xce, 0x63, 0xa8, 0x60, 0x98, 0xda, 0x86, 0x46, 0x72, 0xec, - 0x54, 0xc1, 0xe6, 0x8a, 0x10, 0x23, 0x2d, 0x0c, 0xdd, 0x44, 0x0b, 0xa0, - 0x44, 0xa4, 0x9d, 0x0e, 0x64, 0x31, 0x30, 0x45, 0xb1, 0x97, 0x4c, 0x6d, - 0x9f, 0x43, 0x99, 0x71, 0xa8, 0x9a, 0xe6, 0xbd, 0x3a, 0xe1, 0xff, 0x7f, - 0x33, 0x61, 0xf1, 0x48, 0xda, 0x48, 0x28, 0x10, 0x23, 0x9b, 0x24, 0xeb, - 0xee, 0xbd, 0x35, 0x0e, 0x6e, 0x75, 0x23, 0x20, 0xd6, 0x95, 0x8c, 0xa5, - 0x24, 0xec, 0x44, 0x67, 0x52, 0x2e, 0x78, 0x2a, 0xba, 0x3e, 0x3a, 0x4e, - 0xc9, 0x5c, 0x23, 0xb0, 0xd5, 0xfb, 0x29, 0xaf, 0x9a, 0x0b, 0x90, 0x89, - 0xd8, 0xec, 0xa9, 0xa8, 0x13, 0xfc, 0x22, 0xfa, 0xf2, 0x74, 0x2f, 0x4e, - 0x35, 0xb0, 0x6d, 0x6c, 0xfd, 0xc4, 0xfe, 0xd0, 0x98, 0x3d, 0xe5, 0x43, - 0x0a, 0xd0, 0x33, 0x26, 0x3b, 0x12, 0x7d, 0x65, 0xa1, 0xff, 0xff, 0x6f, - 0x53, 0x0e, 0x28, 0x84, 0xa7, 0xa2, 0x2e, 0xf8, 0x4a, 0xb6, 0xa1, 0x47, - 0xf5, 0xd0, 0x13, 0x9d, 0xd9, 0x50, 0xef, 0x9f, 0x31, 0xb4, 0x13, 0x67, - 0xf9, 0x0a, 0x99, 0xb5, 0x80, 0xec, 0x4a, 0x1a, 0x59, 0x21, 0x3b, 0xce, - 0xc5, 0x7e, 0x96, 0x85, 0x92, 0xc5, 0xb0, 0x75, 0xaa, 0x41, 0x16, 0xa9, - 0xd3, 0xde, 0x13, 0x7d, 0xd9, 0x61, 0x30, 0x1c, 0x73, 0x61, 0x54, 0x90, - 0xcf, 0xd4, 0xe8, 0xfe, 0xbf, 0xbf, 0x36, 0x57, 0x26, 0x38, 0xab, 0x06, - 0xc4, 0x7e, 0x3c, 0x5b, 0x35, 0xd2, 0x7c, 0x2c, 0x0a, 0x82, 0xf2, 0xa8, - 0xf2, 0x8b, 0x48, 0xa9, 0x90, 0x00, 0x01, 0x10, 0x10, 0x14, 0x04, 0x00, - 0x32, 0xa2, 0x06, 0x82, 0x28, 0x90, 0xc2, 0xb4, 0x85, 0xda, 0x01, 0x52, - 0xe9, 0x18, 0x85, 0x60, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x14, 0x41, 0x00, - 0x40, 0xa0, 0x04, 0x40, 0x00, 0x80, 0x50, 0x03, 0x01, 0x10, 0x18, 0x01, - 0x80, 0xd4, 0x14, 0x99, 0x01, 0xfd, 0x07, 0xf8, 0x16, 0x0e, 0xd9, 0x5d, - 0xa3, 0x70, 0xfe, 0xda, 0x17, 0xfa, 0xce, 0x46, 0x9a, 0x99, 0x81, 0x1a, - 0x39, 0xba, 0x63, 0xb1, 0x18, 0x11, 0x58, 0xd7, 0xc7, 0xba, 0x03, 0x3e, - 0x01, 0xf2, 0xf9, 0x4e, 0x12, 0xa3, 0x50, 0x7b, 0xaf, 0x7b, 0x60, 0x5c, - 0x83, 0x23, 0xd2, 0x60, 0x27, 0x84, 0xad, 0xb8, 0x02, 0xed, 0xfe, 0xb4, - 0x9c, 0x08, 0x9f, 0x49, 0xae, 0x55, 0x02, 0x94, 0xc0, 0x1b, 0x90, 0x75, - 0x0b, 0x90, 0xc4, 0xc7, 0x43, 0x9e, 0x67, 0x25, 0x70, 0x61, 0x0d, 0xb8, - 0x7a, 0x97, 0x43, 0xfc, 0xd1, 0x7e, 0x68, 0xed, 0x03, 0xb7, 0x1e, 0x75, - 0xe9, 0x4d, 0x7a, 0x23, 0x18, 0x37, 0x63, 0x6f, 0xab, 0x5f, 0x7c, 0x5b, - 0x1c, 0x05, 0xdf, 0x3f, 0x00, 0x86, 0x37, 0xa0, 0xfa, 0x0c, 0xe0, 0xed, - 0x35, 0x35, 0x2f, 0xd8, 0xd1, 0x75, 0xba, 0x37, 0x34, 0x7e, 0xb0, 0x84, - 0x2a, 0x01, 0x0c, 0x98, 0xed, 0x47, 0xf9, 0x86, 0x81, 0x74, 0x00, 0x5d, - 0x8b, 0x4c, 0x18, 0x8a, 0x31, 0xcd, 0xae, 0x07, 0x44, 0xb5, 0xd5, 0x07, - 0xa0, 0xdf, 0xf4, 0xfa, 0xa6, 0x42, 0xd0, 0x4f, 0x17, 0xd8, 0xdf, 0xb6, - 0x34, 0x44, 0xe3, 0x01, 0xc4, 0xb6, 0x2d, 0xb5, 0x56, 0xc6, 0x2a, 0x1f, - 0x05, 0x6c, 0x35, 0xe0, 0x09, 0x31, 0xef, 0x60, 0xfe, 0xaf, 0x07, 0x80, - 0x32, 0xa0, 0xe9, 0xd3, 0x96, 0x45, 0xa7, 0xaa, 0xb6, 0xfb, 0x03, 0x10, - 0xe3, 0x97, 0x96, 0x8d, 0x3a, 0x01, 0xdd, 0x58, 0x58, 0x78, 0x00, 0xab, - 0xff, 0x06, 0xa0, 0xd6, 0x01, 0x58, 0x08, 0xb7, 0xdc, 0x2d, 0xa7, 0xfb, - 0x22, 0xa8, 0x67, 0x00, 0xe3, 0xcf, 0x82, 0x43, 0xfc, 0x96, 0x1b, 0x40, - 0x63, 0xcf, 0x9d, 0x42, 0x5d, 0x66, 0x40, 0xaa, 0xaf, 0x28, 0x94, 0xd3, - 0x2a, 0xd4, 0x02, 0x13, 0xd2, 0xdf, 0x03, 0x9c, 0x60, 0x6b, 0x16, 0x94, - 0xb4, 0xbe, 0x62, 0xc2, 0x35, 0x60, 0x45, 0x09, 0x23, 0x5a, 0xe0, 0x85, - 0xb3, 0x03, 0x50, 0x68, 0x0c, 0x20, 0xa5, 0xf9, 0x94, 0xd2, 0x35, 0x80, - 0xad, 0x4c, 0x4e, 0x40, 0x41, 0x97, 0x92, 0x75, 0xbe, 0x0c, 0x03, 0x50, - 0x85, 0x08, 0xaf, 0x36, 0x00, 0x68, 0xaf, 0x09, 0xb3, 0x0c, 0x20, 0x4f, - 0x81, 0x6a, 0x6a, 0xf5, 0x0d, 0x70, 0x69, 0x00, 0x4c, 0xb4, 0x0f, 0x59, - 0xe7, 0x31, 0x0a, 0x45, 0x9f, 0xde, 0x90, 0xd6, 0x38, 0x80, 0x6b, 0x2c, - 0xb9, 0x2f, 0xd4, 0x01, 0x40, 0x14, 0xd5, 0xed, 0x8e, 0x01, 0x53, 0xbf, - 0x03, 0x18, 0x1e, 0xb0, 0xc1, 0x85, 0x32, 0xec, 0x78, 0x2b, 0xf0, 0xbb, - 0xbb, 0x6c, 0xf3, 0x4d, 0xdc, 0x73, 0x40, 0xfd, 0x10, 0x09, 0x9e, 0x20, - 0xe2, 0x12, 0x8c, 0xe0, 0xd2, 0xed, 0x80, 0x6b, 0xcc, 0x78, 0x20, 0x03, - 0xd0, 0x5e, 0x06, 0xf4, 0xb0, 0xc4, 0x0e, 0x15, 0x1d, 0x80, 0xb4, 0x76, - 0xdf, 0x49, 0x03, 0x50, 0x82, 0xad, 0xda, 0x8b, 0x5a, 0x61, 0xc2, 0x5e, - 0xb5, 0x1e, 0x46, 0xc0, 0xde, 0xaa, 0x0e, 0x15, 0x06, 0xd2, 0xf4, 0xb2, - 0xd1, 0xed, 0x38, 0x0a, 0x03, 0x18, 0x33, 0x1a, 0x80, 0x61, 0x3e, 0xec, - 0x7c, 0x74, 0xa8, 0x1d, 0x80, 0x1a, 0xce, 0x25, 0x1d, 0x41, 0xd1, 0xc1, - 0x03, 0x28, 0xb5, 0xaf, 0x72, 0x9c, 0x59, 0x7a, 0xe1, 0x7d, 0xc0, 0xa5, - 0x08, 0x1e, 0x18, 0x24, 0xfa, 0xbd, 0x99, 0x4a, 0x31, 0xa0, 0xea, 0xee, - 0xf8, 0x36, 0x60, 0x98, 0xc9, 0x10, 0xd1, 0xa7, 0x35, 0x00, 0x8d, 0x40, - 0x8e, 0x5a, 0x35, 0x0f, 0x80, 0xb1, 0xd4, 0x32, 0x79, 0x40, 0x34, 0x05, - 0x7e, 0x98, 0xc6, 0x80, 0x3e, 0x90, 0x01, 0x65, 0xf4, 0x80, 0x73, 0x08, - 0x64, 0xd7, 0x36, 0xc1, 0x7c, 0xc0, 0x5c, 0x75, 0x00, 0xc5, 0x09, 0x58, - 0x9c, 0x13, 0x01, 0x72, 0x37, 0x9b, 0x79, 0xe4, 0x05, 0xd1, 0x01, 0x04, - 0x98, 0x08, 0x74, 0xfd, 0xfc, 0x3f, 0x1c, 0x00, 0x73, 0x01, 0xfc, 0x1c, - 0xcc, 0x16, 0x43, 0x19, 0x1d, 0xac, 0x61, 0x4b, 0x11, 0xc2, 0xa0, 0xf2, - 0x01, 0x0b, 0x7b, 0x3b, 0xf4, 0xfc, 0x58, 0x5d, 0x2d, 0x5c, 0x01, 0x8c, - 0x62, 0x17, 0x78, 0xbe, 0x60, 0x8c, 0x01, 0x6f, 0x91, 0x49, 0x65, 0x54, - 0x92, 0xe9, 0x01, 0x1e, 0x10, 0x77, 0x35, 0x00, 0xa8, 0xd4, 0xc7, 0x71, - 0x07, 0xd8, 0xcd, 0xa3, 0x7d, 0x69, 0x20, 0xac, 0x07, 0x00, 0x35, 0xc7, - 0x62, 0xee, 0x8c, 0x7d, 0x0c, 0xb8, 0x43, 0x0e, 0x00, 0x08, 0xfb, 0xe7, - 0xec, 0x33, 0x37, 0x04, 0x80, 0x2d, 0x1d, 0xa6, 0x13, 0x34, 0x1b, 0x1d, - 0xc0, 0xca, 0x00, 0x92, 0xed, 0x2e, 0x56, 0xbe, 0x91, 0x80, 0x0c, 0x88, - 0xa6, 0x01, 0xdf, 0x7f, 0x90, 0x49, 0xed, 0x0c, 0xe0, 0x08, 0x73, 0x28, - 0x74, 0xc7, 0xe1, 0xb1, 0x03, 0x5d, 0xc5, 0xab, 0x61, 0x42, 0xdf, 0x03, - 0x43, 0xf3, 0x35, 0x04, 0xcf, 0xc6, 0x1d, 0x79, 0x07, 0x40, 0x22, 0xe4, - 0x68, 0x0d, 0x01, 0x95, 0xad, 0x72, 0x69, 0x00, 0x39, 0x9d, 0x53, 0x8f, - 0x13, 0x0d, 0xb0, 0x29, 0x79, 0x1a, 0x39, 0x20, 0x12, 0x28, 0x9b, 0x02, - 0x8f, 0x74, 0x90, 0x4c, 0xe8, 0xd1, 0x57, 0xf4, 0x01, 0x44, 0x04, 0xe0, - 0x0c, 0x82, 0x91, 0xc5, 0x4f, 0x8f, 0xc6, 0x00, 0x43, 0x85, 0x65, 0xc8, - 0xe6, 0x34, 0x1d, 0x80, 0xc0, 0xca, 0xdb, 0x57, 0x6c, 0x00, 0x72, 0x42, - 0x5f, 0xd0, 0x49, 0x57, 0x47, 0xd4, 0x97, 0x18, 0x18, 0x80, 0x68, 0x8e, - 0x0a, 0xf1, 0x6b, 0x34, 0xf1, 0x60, 0x2c, 0x41, 0x29, 0xd3, 0x3d, 0x55, - 0x95, 0xb1, 0x3c, 0xd4, 0x95, 0x42, 0xef, 0xe7, 0xca, 0x00, 0x2e, 0xce, - 0x25, 0xc2, 0xca, 0xf5, 0x00, 0x17, 0x3b, 0x8c, 0x42, 0x88, 0x03, 0xde, - 0x97, 0xe1, 0x3a, 0x74, 0xb0, 0x33, 0xe0, 0x8f, 0x47, 0xeb, 0x2a, 0x5f, - 0x36, 0x3e, 0x5a, 0xff, 0xc5, 0x80, 0xb9, 0x13, 0xa9, 0x1f, 0xf8, 0x86, - 0xc9, 0x51, 0xf8, 0x4c, 0xaa, 0xe1, 0x65, 0x80, 0xb0, 0x8b, 0x91, 0xec, - 0xcc, 0xbf, 0x70, 0x19, 0x98, 0x03, 0x10, 0xf0, 0x38, 0x40, 0xc4, 0x65, - 0xbe, 0x41, 0xb2, 0x58, 0x3f, 0xe0, 0xcc, 0x0e, 0x08, 0x2b, 0x73, 0xf4, - 0xdd, 0x86, 0x06, 0xa0, 0xc6, 0x8f, 0x1a, 0x32, 0x66, 0x50, 0x8e, 0xe1, - 0x59, 0x67, 0x00, 0xed, 0x66, 0x1d, 0xdd, 0xfa, 0x7b, 0xe2, 0x56, 0x89, - 0xd9, 0xa0, 0x4f, 0x41, 0x94, 0x28, 0xb8, 0xc6, 0xc7, 0x64, 0xde, 0x9b, - 0x64, 0x44, 0x33, 0x39, 0xb5, 0x6c, 0xb9, 0x42, 0xe7, 0x7e, 0x16, 0xd2, - 0x01, 0x12, 0x03, 0xb3, 0x48, 0x47, 0x6b, 0x75, 0x26, 0x19, 0x8c, 0xac, - 0x6f, 0xb1, 0x6f, 0xdc, 0x04, 0x27, 0x3a, 0x00, 0xd6, 0xae, 0xfa, 0xe1, - 0xf7, 0x30, 0xa4, 0xdb, 0xd5, 0x86, 0x5a, 0x07, 0x11, 0xde, 0xea, 0xf4, - 0xb0, 0x83, 0x16, 0xbb, 0xc6, 0x00, 0x6e, 0xf2, 0x6b, 0x40, 0x81, 0x01, - 0x67, 0x0e, 0xa9, 0x82, 0x23, 0x04, 0x34, 0xed, 0x02, 0xf5, 0xe4, 0x0e, - 0x58, 0xe8, 0x8a, 0x58, 0x57, 0xb0, 0x56, 0x65, 0x3d, 0x40, 0x64, 0x03, - 0x6e, 0x7b, 0x07, 0x20, 0x99, 0x90, 0x36, 0x95, 0x9f, 0xdf, 0x3d, 0xe8, - 0x00, 0xa0, 0x57, 0x8f, 0x6d, 0xa4, 0xb3, 0x1d, 0x7a, 0x06, 0xa8, 0x26, - 0x41, 0xb0, 0x8c, 0x9c, 0x10, 0x85, 0x6c, 0xb4, 0x31, 0xa6, 0x5b, 0x7a, - 0x10, 0x51, 0x15, 0x3c, 0xa2, 0x42, 0xd3, 0x23, 0x02, 0xc0, 0x17, 0x7e, - 0x03, 0x28, 0xba, 0xce, 0x9b, 0xae, 0xdd, 0x1a, 0x19, 0xd0, 0x15, 0xac, - 0xeb, 0x20, 0x3c, 0x3a, 0x00, 0xc6, 0xbb, 0x8a, 0xd5, 0x64, 0xc2, 0x21, - 0x1d, 0x6c, 0x15, 0x5a, 0xd3, 0x44, 0x98, 0x14, 0x95, 0xb3, 0xb7, 0xdd, - 0xa6, 0xea, 0x06, 0x54, 0x78, 0xc3, 0xe8, 0x79, 0x9b, 0x86, 0x29, 0x76, - 0x8b, 0x6b, 0xaa, 0x0d, 0xa8, 0x2f, 0x22, 0x2a, 0xeb, 0x68, 0x81, 0x6c, - 0x56, 0xfd, 0x79, 0xac, 0x79, 0x4b, 0xa0, 0x01, 0x3f, 0x17, 0x43, 0x82, - 0xb4, 0xd5, 0x00, 0x14, 0xb7, 0xf5, 0x00, 0xf4, 0x15, 0xa8, 0xd7, 0x4b, - 0xb1, 0xbc, 0xa8, 0x36, 0x98, 0xf0, 0x8c, 0xe7, 0xf4, 0x7b, 0x35, 0xd8, - 0xad, 0x0d, 0x5f, 0x9d, 0x96, 0xab, 0xed, 0x48, 0xe2, 0xdc, 0x1c, 0xbe, - 0x12, 0xfa, 0x41, 0x6f, 0xf5, 0x1e, 0xb6, 0x9f, 0xee, 0xac, 0x21, 0xf4, - 0xf6, 0x00, 0x38, 0xb1, 0x1f, 0xfd, 0xd0, 0x0e, 0xc7, 0xdd, 0xa0, 0x39, - 0x07, 0x8c, 0x35, 0x1f, 0x7e, 0xcc, 0xbf, 0xf6, 0xe0, 0x06, 0x66, 0x7d, - 0x10, 0x3f, 0xc5, 0x3e, 0xde, 0x42, 0xf9, 0x3d, 0x00, 0x54, 0x81, 0x67, - 0x8a, 0xe6, 0x63, 0x0d, 0x01, 0xd0, 0x31, 0xe0, 0x6e, 0xd0, 0xe1, 0x59, - 0xf6, 0x1b, 0xf7, 0x0d, 0x52, 0x06, 0x80, 0x61, 0x4f, 0xe8, 0x77, 0xdd, - 0x6f, 0x48, 0x20, 0x1d, 0xbb, 0x2a, 0x16, 0x8b, 0x54, 0x87, 0x92, 0x83, - 0xe6, 0x8f, 0x55, 0x59, 0x06, 0x00, 0xe9, 0xc5, 0xce, 0x21, 0x63, 0x87, - 0xaf, 0x86, 0xcc, 0xba, 0xd6, 0xe7, 0x00, 0xf6, 0x91, 0x92, 0x92, 0xea, - 0xe8, 0x42, 0x06, 0x69, 0x13, 0xf5, 0x00, 0xd0, 0xb0, 0xa7, 0xcb, 0x4c, - 0xb0, 0xd2, 0x2d, 0x28, 0x63, 0xf0, 0x6a, 0xc7, 0x80, 0x6a, 0x19, 0xb2, - 0x66, 0x51, 0xf3, 0xb1, 0x21, 0xa0, 0x48, 0xad, 0x1e, 0x80, 0x62, 0xaf, - 0x00, 0xf4, 0xa5, 0x4e, 0x83, 0x75, 0x1b, 0xfe, 0x00, 0xc4, 0xcf, 0x55, - 0xb2, 0x50, 0xa6, 0xeb, 0x38, 0xed, 0x8f, 0xd3, 0x1d, 0x00, 0xf6, 0xe3, - 0x90, 0x1c, 0x60, 0x9e, 0x8e, 0xeb, 0x0b, 0xba, 0x44, 0x06, 0x68, 0xbb, - 0xd3, 0x10, 0x63, 0x35, 0xe1, 0x86, 0x5c, 0x5c, 0x2b, 0x85, 0xa6, 0xe7, - 0x38, 0x2c, 0x18, 0x83, 0x1f, 0x8f, 0x9b, 0x8e, 0x4d, 0x26, 0xcd, 0x34, - 0x0c, 0x66, 0x1d, 0x70, 0xb7, 0x01, 0xe6, 0x02, 0xa8, 0x51, 0x63, 0xcf, - 0xbb, 0x03, 0xca, 0x85, 0xc6, 0x9c, 0xf6, 0xf1, 0x51, 0xe0, 0x60, 0x07, - 0x40, 0x86, 0xf0, 0x1e, 0x6e, 0xef, 0x61, 0x10, 0xd9, 0x36, 0xcc, 0xfc, - 0x58, 0xe2, 0x37, 0x0d, 0x58, 0xb7, 0xbe, 0xca, 0xc9, 0xd8, 0xcd, 0xaa, - 0xd5, 0x5b, 0x77, 0x83, 0xcb, 0x0e, 0x30, 0xce, 0xc8, 0xb8, 0xcd, 0xbf, - 0x1e, 0x63, 0x04, 0xad, 0xb7, 0xcd, 0x43, 0x62, 0x4c, 0xe0, 0x1a, 0xd4, - 0x21, 0xe2, 0xdd, 0x33, 0xdf, 0xb1, 0xdd, 0xdc, 0x01, 0x22, 0x18, 0xce, - 0xa1, 0xd8, 0xcb, 0x67, 0xd5, 0x38, 0x4a, 0xbc, 0xd5, 0x81, 0x3d, 0x03, - 0x98, 0x35, 0x60, 0x41, 0x85, 0x0c, 0x1d, 0xe7, 0x76, 0xf8, 0x11, 0x52, - 0x76, 0xf6, 0x06, 0x16, 0x02, 0x45, 0xc8, 0xd8, 0x2f, 0x5e, 0x57, 0xbc, - 0x3b, 0x89, 0x97, 0x09, 0x3e, 0x03, 0x34, 0x1a, 0x9d, 0x37, 0x87, 0x48, - 0x0a, 0xe0, 0xa7, 0x4f, 0x8c, 0x3a, 0xa2, 0xaf, 0xfd, 0x7b, 0x80, 0xcf, - 0xe5, 0x18, 0x61, 0x68, 0xba, 0x61, 0x8b, 0x09, 0xaa, 0xa3, 0x0c, 0x47, - 0x3c, 0x43, 0x03, 0xac, 0xa3, 0x2e, 0x5e, 0x72, 0x0c, 0x80, 0x19, 0x61, - 0xe6, 0x6e, 0x0e, 0xd9, 0xe8, 0xe8, 0xaf, 0x11, 0x9b, 0x4a, 0x73, 0x7a, - 0x61, 0x66, 0xf0, 0x54, 0x1d, 0x18, 0xc8, 0x23, 0x36, 0xbf, 0xb5, 0xf4, - 0x86, 0x54, 0xed, 0xb5, 0x91, 0xee, 0xb8, 0xbc, 0xde, 0xc3, 0x87, 0x9b, - 0x2f, 0x81, 0xf2, 0xee, 0xa3, 0xec, 0x02 +#include "testcard-zstd.inl" }; /** diff --git a/contrib/single_file_decoder/examples/testcard-dxt1.inl b/contrib/single_file_decoder/examples/testcard-dxt1.inl new file mode 100644 index 00000000000..e099e66fcc1 --- /dev/null +++ b/contrib/single_file_decoder/examples/testcard-dxt1.inl @@ -0,0 +1,2731 @@ +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0xb5, +0xde, 0xf7, 0x30, 0x84, 0x00, 0x15, 0x35, 0x20, 0xdf, 0xff, 0x30, 0x84, +0x00, 0xd4, 0x80, 0x54, 0xde, 0xf7, 0x30, 0x84, 0x00, 0x2b, 0x7e, 0x55, +0xde, 0xf7, 0x10, 0x84, 0x00, 0xa0, 0x55, 0x55, 0xdf, 0xff, 0xe7, 0x39, +0x00, 0x2a, 0x3f, 0x3f, 0x82, 0x10, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0xff, 0xff, 0x28, 0x42, 0x00, 0xff, 0xff, 0xff, 0x41, 0x08, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x3f, 0x3f, 0x3f, +0xff, 0xff, 0x08, 0x42, 0x00, 0xa8, 0xfc, 0xfc, 0xde, 0xf7, 0x30, 0x84, +0x00, 0x02, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, 0x00, 0xfa, 0xaf, 0x55, +0xdf, 0xff, 0x30, 0x84, 0x00, 0x15, 0x20, 0x35, 0xde, 0xf7, 0x30, 0x84, +0x00, 0x54, 0x54, 0x80, 0xff, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x57, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x10, 0x84, 0x15, 0x15, 0x15, 0x2d, 0xff, 0xff, 0x30, 0x84, +0x54, 0xd4, 0x88, 0x5c, 0xff, 0xff, 0x10, 0x84, 0xb5, 0xe2, 0x57, 0x55, +0x7d, 0xef, 0x30, 0x84, 0xe0, 0x55, 0x55, 0x55, 0x41, 0x08, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x30, 0x84, 0xd4, 0x54, 0x54, 0x54, +0x9d, 0xef, 0x30, 0x84, 0x82, 0xd5, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, +0x57, 0xe2, 0xb5, 0x55, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x38, 0x2d, +0xff, 0xff, 0x10, 0x84, 0x54, 0x54, 0x54, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x41, 0x08, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0x9e, 0xf7, 0x10, 0x84, 0x55, 0x55, 0x35, 0xe2, +0x5c, 0xe7, 0x10, 0x84, 0xb5, 0x83, 0x5c, 0x55, 0xff, 0xff, 0x30, 0x84, +0x38, 0x15, 0x15, 0x15, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xf7, 0x30, 0x84, +0x88, 0x94, 0x54, 0x54, 0x5c, 0xe7, 0x10, 0x84, 0x57, 0x70, 0x0d, 0xd5, +0xbe, 0xf7, 0x30, 0x84, 0x55, 0x55, 0x57, 0x62, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x08, 0x42, +0x3f, 0x3f, 0x2f, 0x00, 0x51, 0x8c, 0xdf, 0xff, 0x61, 0x25, 0x01, 0x55, +0xff, 0xff, 0x49, 0x4a, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x69, 0x4a, +0x2f, 0xff, 0xff, 0x00, 0x51, 0x8c, 0xff, 0xff, 0x42, 0x66, 0x60, 0x55, +0xff, 0xff, 0x28, 0x42, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, +0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, +0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0xde, 0xf7, 0x10, 0x84, 0x00, 0x55, 0xd5, 0x25, 0xbe, 0xf7, 0x30, 0x84, +0x00, 0xc9, 0x58, 0x57, 0xff, 0xff, 0x08, 0x42, 0x00, 0x3f, 0x3f, 0x3f, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, +0x00, 0xbc, 0xfc, 0xfc, 0xbe, 0xf7, 0x10, 0x84, 0x00, 0x58, 0xc9, 0x35, +0xff, 0xff, 0x10, 0x84, 0x00, 0x55, 0x55, 0x56, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, +0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, +0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, +0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, +0xff, 0xff, 0xff, 0xff, 0xe9, 0x93, 0xc7, 0x8b, 0xaa, 0xaa, 0xaa, 0x2a, +0xbe, 0xf7, 0x10, 0x84, 0x54, 0x94, 0x8c, 0x70, 0x7d, 0xef, 0x10, 0x84, +0x63, 0x5c, 0x55, 0x55, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0x71, 0x8c, 0xcf, 0x7b, 0xbf, 0xff, 0xff, 0xff, 0x9d, 0xef, 0x10, 0x84, +0x72, 0x8d, 0x95, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x15, 0x15, 0x1c, 0x23, +0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, +0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, +0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x99, 0xff, 0x00, 0x5a, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, +0xff, 0xff, 0xff, 0xff, 0x56, 0xd6, 0xa1, 0x72, 0xff, 0xff, 0xff, 0x3f, +0x5c, 0xef, 0x2a, 0x94, 0x15, 0x8d, 0x73, 0x54, 0x41, 0x08, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x30, 0x84, 0x25, 0x15, 0x15, 0x15, 0x7c, 0xf7, 0x09, 0x94, +0x55, 0x5c, 0x73, 0x85, 0x09, 0x94, 0xa7, 0x8b, 0xff, 0xff, 0xff, 0xfe, +0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xc1, 0x59, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x99, 0xff, 0x00, 0x5a, +0xff, 0xff, 0xff, 0xff, 0x7c, 0xf7, 0xc8, 0x8b, 0x55, 0x55, 0xd5, 0x35, +0x3b, 0xef, 0x09, 0x94, 0x05, 0x61, 0x58, 0x57, 0x2a, 0x9c, 0xc7, 0x8b, +0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xf9, 0xe6, 0x60, 0x6a, 0x3f, 0xff, 0xff, 0xff, +0x9d, 0xf7, 0x09, 0x94, 0x56, 0x52, 0x49, 0x35, 0xc2, 0x72, 0xce, 0xac, +0xaa, 0xaa, 0xaa, 0xa9, 0xf6, 0xff, 0xc1, 0x59, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x10, 0x84, 0x00, 0x54, 0xd4, 0x34, +0xde, 0xf7, 0xef, 0x7b, 0x00, 0x73, 0x5c, 0x57, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0xde, 0xf7, 0xef, 0x7b, 0x00, 0x73, 0xcd, 0x35, +0xff, 0xff, 0x10, 0x84, 0x00, 0x15, 0x15, 0x17, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x5d, 0xf7, 0xef, 0xaa, 0x55, 0x55, 0xd5, 0x35, +0xde, 0xf7, 0xef, 0x7b, 0xcc, 0x70, 0x5c, 0x54, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x2c, 0x63, 0xd3, 0x9c, 0x6a, 0xaa, 0xaa, 0xaa, 0xde, 0xf7, 0xef, 0x7b, +0x1c, 0x33, 0x0d, 0x35, 0xd4, 0x62, 0x57, 0x94, 0xaa, 0xaa, 0xaa, 0xa9, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xd8, 0xdd, 0xcb, 0x99, 0xff, 0xff, 0xff, 0x3f, +0xdb, 0xee, 0x30, 0xb3, 0x85, 0x61, 0x50, 0x54, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x1d, 0xe7, 0xb6, 0x83, 0x54, 0x52, 0x41, 0x85, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x30, 0xb3, 0x0f, 0xb3, 0xff, 0xff, 0xff, 0xbf, +0x9e, 0xf7, 0x30, 0xb3, 0x35, 0xcd, 0x71, 0x5a, 0xf2, 0xbb, 0xae, 0xaa, +0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, +0x76, 0xfe, 0x01, 0xd8, 0xff, 0xff, 0xff, 0xff, 0x76, 0xfe, 0x01, 0xd8, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, +0xff, 0xff, 0xff, 0xff, 0xda, 0xf7, 0x81, 0xf7, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x5e, 0xef, 0x96, 0x7b, +0x15, 0xd5, 0x55, 0x55, 0x9e, 0xf7, 0xb6, 0x7b, 0x57, 0x5c, 0x53, 0x69, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x7d, 0xf7, 0x2f, 0xb3, 0x95, 0x35, 0xc5, 0x69, 0xdb, 0xee, 0x0f, 0xb3, +0x54, 0x57, 0x55, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x5e, 0xef, 0xf2, 0x49, 0x8f, 0x3f, 0xbf, 0xff, 0x7e, 0xef, 0x96, 0x7b, +0x55, 0x57, 0x54, 0x5a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x7d, 0xf7, 0x2f, 0xb3, 0x55, 0x55, 0x95, 0x35, 0x7d, 0xf7, 0x30, 0xb3, +0x53, 0x5c, 0x56, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x7e, 0xef, 0xb6, 0x83, 0x71, 0x4d, 0xa5, 0x15, +0x73, 0x5a, 0xb8, 0x9c, 0xaa, 0xaa, 0xaa, 0xa9, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfc, 0xee, 0x70, 0xb3, +0xc5, 0x49, 0x51, 0x58, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x19, 0xa5, 0xaf, 0x28, 0x2a, 0xaa, 0xaa, 0xaa, 0x1d, 0xe7, 0xd6, 0x83, +0x54, 0x58, 0x51, 0x49, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x10, 0x84, +0x15, 0x15, 0x35, 0x00, 0x9e, 0xf7, 0x30, 0xb3, 0x54, 0x57, 0x55, 0x55, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0x41, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x41, 0x08, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x3d, 0xe7, 0xb6, 0x7b, 0xc5, 0x35, 0x15, 0xd5, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x08, 0x42, +0x00, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x71, 0x8c, 0x00, 0x11, 0x1b, 0x14, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x1f, 0x62, 0x1e, 0x5a, 0xea, 0xaa, 0xaa, 0xea, +0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfa, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, +0x5f, 0x57, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, 0xfa, 0xfa, 0xfa, 0xfa, +0xfc, 0x51, 0xba, 0x51, 0xfe, 0xfe, 0xfa, 0xfe, 0xda, 0x51, 0x99, 0x49, +0xea, 0xea, 0xe8, 0xea, 0xb9, 0x51, 0x98, 0x49, 0x7e, 0x7e, 0x7e, 0x7e, +0x97, 0x49, 0x76, 0x41, 0xe8, 0xe8, 0xe8, 0xe8, 0x97, 0x49, 0x75, 0x41, +0x5f, 0x5f, 0x5f, 0x5f, 0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, +0x53, 0x39, 0x32, 0x39, 0x7e, 0x7e, 0x5e, 0x7e, 0x31, 0x39, 0x10, 0x31, +0xfa, 0xfa, 0x78, 0x7a, 0x0f, 0x31, 0xcd, 0x28, 0xa0, 0x80, 0x80, 0x80, +0xee, 0x30, 0xed, 0x28, 0x5e, 0x7e, 0x5e, 0x5e, 0xcc, 0x28, 0xaa, 0x20, +0xa0, 0xa0, 0xa0, 0xa0, 0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, +0xaa, 0x20, 0x88, 0x18, 0xfa, 0xfa, 0xfa, 0xfa, 0x88, 0x18, 0x66, 0x18, +0xe8, 0xe8, 0xe8, 0xe8, 0x87, 0x18, 0x45, 0x10, 0xfa, 0xfa, 0xfa, 0xfa, +0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, +0xa8, 0xe8, 0xa8, 0xe8, 0x44, 0x10, 0x22, 0x08, 0x5f, 0x7f, 0x7f, 0x7f, +0x22, 0x08, 0x01, 0x08, 0xea, 0xfa, 0xfa, 0xea, 0x01, 0x08, 0x00, 0x00, +0xaa, 0xea, 0xaa, 0xaa, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x51, 0x8c, +0x00, 0x50, 0x78, 0x44, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x69, 0x4a, 0xbf, 0x3f, 0x2f, 0x8f, +0xff, 0xff, 0xef, 0x7b, 0x16, 0x17, 0x15, 0x15, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x1f, 0x62, 0x1e, 0x5a, 0xaa, 0xea, 0xaa, 0xea, 0x1f, 0x62, 0xfd, 0x59, +0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, 0x57, 0x57, 0x57, 0x57, +0xfd, 0x59, 0xdb, 0x51, 0xfa, 0xfa, 0xfa, 0xfa, 0xdb, 0x51, 0xb9, 0x51, +0xa0, 0xa0, 0xa0, 0x80, 0xba, 0x51, 0xb9, 0x49, 0xe8, 0xe8, 0xe8, 0xe8, +0xda, 0x51, 0x98, 0x49, 0x5f, 0x7f, 0x7f, 0x5f, 0x97, 0x49, 0x76, 0x41, +0xe8, 0xe8, 0xe8, 0xe0, 0x97, 0x49, 0x75, 0x41, 0x57, 0x57, 0x5f, 0x5f, +0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, 0x53, 0x39, 0x32, 0x39, +0x5c, 0x5e, 0x7e, 0x5e, 0x32, 0x39, 0x0f, 0x31, 0xfa, 0xfa, 0xfa, 0xfa, +0x0f, 0x31, 0xee, 0x28, 0xe0, 0xe0, 0xa0, 0xa0, 0x10, 0x31, 0xed, 0x28, +0x5f, 0x5f, 0x5f, 0x5f, 0xcc, 0x28, 0xcb, 0x20, 0xe0, 0xe8, 0xe8, 0xe0, +0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, 0xa9, 0x20, 0x88, 0x18, +0xe8, 0xe8, 0xe8, 0xe8, 0x88, 0x18, 0x66, 0x18, 0xe8, 0xe8, 0xe8, 0xe8, +0x67, 0x18, 0x65, 0x10, 0xfe, 0xfa, 0xfe, 0xfa, 0x66, 0x10, 0x44, 0x10, +0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, 0xa8, 0xa8, 0xa8, 0xa8, +0x44, 0x10, 0x22, 0x08, 0x5f, 0x7f, 0x7f, 0x7f, 0x22, 0x08, 0x01, 0x08, +0xf8, 0xe8, 0xea, 0xea, 0x01, 0x08, 0x00, 0x00, 0xaa, 0xe8, 0xea, 0xe8, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0xe4, 0x34, 0x94, 0xd4, +0x3c, 0xe7, 0x69, 0x4a, 0xff, 0xff, 0xfe, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x9d, 0xef, 0x30, 0x84, 0x4d, 0x79, 0x51, 0x5a, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x1f, 0x62, 0x1e, 0x5a, +0xea, 0xea, 0xea, 0xea, 0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfe, 0xfa, 0xfe, +0x1e, 0x5a, 0xfd, 0x59, 0x57, 0x5f, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, +0xfa, 0xfa, 0xfa, 0xfa, 0xdb, 0x51, 0xba, 0x51, 0xe0, 0xe0, 0xe0, 0xe0, +0xba, 0x51, 0xb9, 0x49, 0xe8, 0xe8, 0xe8, 0xe8, 0xda, 0x51, 0x98, 0x49, +0x5f, 0x5f, 0x5f, 0x5f, 0x97, 0x49, 0x76, 0x41, 0xe8, 0xe0, 0xe8, 0xe0, +0x97, 0x49, 0x75, 0x41, 0x5f, 0x5f, 0x5f, 0x5f, 0x75, 0x41, 0x32, 0x39, +0xea, 0xea, 0xea, 0xea, 0x53, 0x39, 0x32, 0x39, 0x7e, 0x7a, 0x7a, 0x7e, +0x31, 0x39, 0x10, 0x31, 0x78, 0xf8, 0xf8, 0x78, 0x0f, 0x31, 0xee, 0x28, +0xa0, 0xe0, 0xa0, 0xe0, 0x10, 0x31, 0xed, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, +0xed, 0x28, 0xaa, 0x20, 0xea, 0xea, 0xea, 0xea, 0xcc, 0x28, 0xaa, 0x20, +0x5f, 0x5f, 0x5f, 0x5f, 0xaa, 0x20, 0x88, 0x18, 0xfa, 0xfa, 0xfa, 0xfa, +0x88, 0x18, 0x66, 0x18, 0xe8, 0xe8, 0xe8, 0xe8, 0x67, 0x18, 0x65, 0x10, +0xfa, 0xfa, 0xf8, 0xfa, 0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, +0x44, 0x10, 0x22, 0x08, 0xa8, 0xa8, 0xa8, 0xa8, 0x44, 0x10, 0x22, 0x08, +0x5f, 0x5f, 0x7f, 0x5f, 0x22, 0x08, 0x01, 0x08, 0xea, 0xea, 0xea, 0xe8, +0x01, 0x08, 0x00, 0x00, 0xea, 0xea, 0xe8, 0xea, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, 0x9e, 0xf7, 0x30, 0x84, +0x5c, 0x5b, 0x51, 0x69, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0xff, 0xff, 0xef, 0x7b, 0x55, 0xd5, 0x95, 0x00, 0xbe, 0xf7, 0x10, 0x84, +0x5c, 0x54, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x1f, 0x62, 0x1e, 0x5a, 0xea, 0xaa, 0xea, 0xea, +0x1f, 0x62, 0xfd, 0x59, 0xfe, 0xfe, 0xfe, 0xfe, 0x1e, 0x5a, 0xfd, 0x59, +0x57, 0x57, 0x57, 0x57, 0xfd, 0x59, 0xdb, 0x51, 0xea, 0xfa, 0xfa, 0xea, +0xdb, 0x51, 0xb9, 0x51, 0x80, 0x80, 0xa0, 0x80, 0xba, 0x51, 0xb8, 0x49, +0xa8, 0xa8, 0xa8, 0xa0, 0xb9, 0x51, 0x98, 0x49, 0x7e, 0x7e, 0x7e, 0x7e, +0x97, 0x49, 0x76, 0x41, 0xa8, 0xe8, 0xe8, 0xe0, 0x97, 0x49, 0x75, 0x41, +0x5f, 0x5f, 0x57, 0x5f, 0x75, 0x41, 0x32, 0x39, 0xea, 0xea, 0xea, 0xea, +0x53, 0x39, 0x32, 0x39, 0x58, 0x7e, 0x7a, 0x7a, 0x32, 0x39, 0x0f, 0x31, +0xfa, 0xfa, 0xfa, 0xfa, 0x0f, 0x31, 0xee, 0x28, 0xa0, 0xe0, 0xe0, 0xe0, +0xef, 0x30, 0xed, 0x28, 0x5e, 0x7f, 0x5e, 0x7f, 0xed, 0x28, 0xaa, 0x20, +0xea, 0xea, 0xea, 0xea, 0xcc, 0x28, 0xaa, 0x20, 0x5f, 0x5f, 0x5f, 0x5f, +0xa9, 0x20, 0x88, 0x18, 0xf8, 0xe8, 0xe8, 0xe8, 0x88, 0x18, 0x66, 0x18, +0xe8, 0xe8, 0xe8, 0xe8, 0x67, 0x18, 0x65, 0x10, 0xfa, 0xfa, 0xfa, 0xfa, +0x66, 0x10, 0x44, 0x10, 0x7e, 0x7e, 0x7e, 0x7e, 0x44, 0x10, 0x22, 0x08, +0xa8, 0xa8, 0xa8, 0xe0, 0x44, 0x10, 0x22, 0x08, 0x7f, 0x7f, 0x5f, 0x5f, +0x22, 0x08, 0x01, 0x08, 0xfa, 0xf8, 0xfa, 0xf8, 0x01, 0x08, 0x00, 0x00, +0xa8, 0xa8, 0xa8, 0xa8, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x4d, 0xc5, 0xb5, 0x00, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0xff, 0xff, 0x30, 0x84, +0x00, 0xe5, 0x45, 0x6d, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x8c, 0xf8, 0x6b, 0xf0, 0xaa, 0xaa, 0xaa, 0xea, 0x8c, 0xf0, 0x6b, 0xf0, +0xff, 0xdf, 0xff, 0xff, 0x8b, 0xf0, 0x6b, 0xe8, 0x5f, 0x5f, 0x7f, 0x5f, +0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, +0xe0, 0xa0, 0xe0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, 0xf8, 0xf8, 0x78, 0xf8, +0x69, 0xc8, 0x49, 0xb8, 0xa8, 0xe8, 0xe8, 0xe8, 0x69, 0xc0, 0x48, 0xb0, +0xfa, 0xfa, 0xfa, 0xfe, 0x69, 0xb8, 0x48, 0xa8, 0x5f, 0x5f, 0x5f, 0x5f, +0x48, 0xa8, 0x47, 0x98, 0x7a, 0xfa, 0xfa, 0xfa, 0x47, 0x98, 0x47, 0x90, +0x7c, 0x5c, 0x58, 0x5c, 0x47, 0x90, 0x46, 0x80, 0x7a, 0x7e, 0x7a, 0x7e, +0x46, 0x80, 0x45, 0x70, 0xf8, 0xf8, 0xf8, 0xf8, 0x45, 0x70, 0x25, 0x68, +0x78, 0x78, 0x78, 0x78, 0x25, 0x68, 0x24, 0x58, 0xfa, 0xfa, 0xfa, 0xfa, +0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, +0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, +0x23, 0x38, 0x02, 0x28, 0xea, 0xea, 0xea, 0xea, 0x22, 0x30, 0x02, 0x20, +0xfa, 0xfe, 0xfa, 0xfa, 0x02, 0x20, 0x01, 0x18, 0xe8, 0xe8, 0xe8, 0xf8, +0x01, 0x18, 0x01, 0x10, 0xf8, 0xf8, 0xf8, 0xe8, 0x01, 0x10, 0x00, 0x08, +0xe8, 0xe8, 0xe8, 0xe0, 0x01, 0x10, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0xff, 0xff, 0x10, 0x84, 0x00, 0xd5, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, +0x00, 0x56, 0x54, 0x5e, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0x7d, 0xef, 0x10, 0x84, 0x79, 0x51, 0x53, 0x5a, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0xf8, 0x6b, 0xf0, +0xe8, 0xa8, 0xe8, 0xa8, 0x8b, 0xf8, 0x6b, 0xe8, 0xea, 0xfa, 0xfa, 0xea, +0x8b, 0xf0, 0x6b, 0xe8, 0x57, 0x57, 0x57, 0x57, 0x6b, 0xe8, 0x6a, 0xd8, +0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, 0xa0, 0xa0, 0xa0, 0xe0, +0x6a, 0xd0, 0x69, 0xc8, 0x60, 0x68, 0xf8, 0xe8, 0x6a, 0xd0, 0x69, 0xc0, +0x5f, 0x5f, 0x5f, 0x5f, 0x69, 0xc0, 0x48, 0xb0, 0xfa, 0xfa, 0xfa, 0xfa, +0x68, 0xb0, 0x48, 0xa8, 0x7e, 0x7a, 0x7e, 0x7a, 0x48, 0xa8, 0x47, 0x98, +0x7a, 0xfa, 0x7a, 0xfa, 0x47, 0x90, 0x47, 0x98, 0x09, 0x09, 0x09, 0x09, +0x47, 0x90, 0x46, 0x80, 0x7e, 0x7e, 0x7e, 0x7e, 0x46, 0x80, 0x25, 0x70, +0xe8, 0xe8, 0xe8, 0xf8, 0x46, 0x78, 0x25, 0x68, 0x7e, 0x7e, 0x7e, 0x7e, +0x45, 0x68, 0x24, 0x58, 0xfa, 0xfe, 0xfa, 0xfa, 0x24, 0x58, 0x24, 0x50, +0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, 0xfa, 0xfa, 0xfa, 0xfa, +0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, 0x23, 0x38, 0x02, 0x28, +0xea, 0xea, 0xfa, 0xea, 0x02, 0x30, 0x22, 0x20, 0xfe, 0xfe, 0xfa, 0xfa, +0x22, 0x28, 0x01, 0x18, 0x7e, 0x7e, 0xfe, 0xfe, 0x01, 0x18, 0x01, 0x10, +0xe8, 0xe8, 0xe8, 0xe8, 0x01, 0x10, 0x00, 0x08, 0xe8, 0xe8, 0xe8, 0xe0, +0x01, 0x08, 0x00, 0x08, 0xff, 0xff, 0xfb, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x10, 0x84, 0x5b, 0x51, 0x71, 0x69, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xdf, 0xff, 0x10, 0x84, 0x54, 0x54, 0xd4, 0x94, +0x1c, 0xe7, 0xef, 0x7b, 0x5c, 0x54, 0x54, 0x56, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x8c, 0xf8, 0x6b, 0xf0, 0xfa, 0xea, 0xea, 0xea, +0x8c, 0xf0, 0x6b, 0xf0, 0xfa, 0xfe, 0xfa, 0xff, 0x8b, 0xf0, 0x6b, 0xe8, +0x5f, 0x5f, 0x5e, 0x5f, 0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, +0x6a, 0xd8, 0x6a, 0xd0, 0xe0, 0xa0, 0xa0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, +0xf8, 0xe8, 0xf8, 0xf8, 0x6a, 0xc8, 0x69, 0xc0, 0x7e, 0x7e, 0x5e, 0x5e, +0x69, 0xc0, 0x48, 0xb0, 0xfa, 0xfa, 0xfa, 0xfa, 0x68, 0xb0, 0x48, 0xa8, +0x7e, 0x5e, 0x7a, 0x7e, 0x48, 0xa8, 0x47, 0x98, 0x7a, 0x7a, 0x7a, 0xfa, +0x47, 0x90, 0x47, 0x98, 0x09, 0x09, 0x09, 0x09, 0x47, 0x90, 0x46, 0x80, +0x7e, 0x7e, 0x7a, 0x7e, 0x46, 0x80, 0x25, 0x70, 0xfa, 0xea, 0xea, 0xea, +0x46, 0x78, 0x25, 0x68, 0x7e, 0x7e, 0x7e, 0x7e, 0x45, 0x68, 0x24, 0x58, +0xfe, 0xfa, 0xfe, 0xfe, 0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, +0x24, 0x50, 0x23, 0x40, 0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, +0x78, 0x78, 0x78, 0x78, 0x23, 0x38, 0x22, 0x28, 0xea, 0xfa, 0xfa, 0xfa, +0x22, 0x30, 0x02, 0x20, 0xfa, 0xfe, 0xfa, 0xfa, 0x22, 0x28, 0x01, 0x18, +0xfe, 0xfe, 0xfe, 0xfe, 0x01, 0x18, 0x01, 0x10, 0xe8, 0xe8, 0xe8, 0xf8, +0x01, 0x10, 0x00, 0x08, 0xe8, 0xe8, 0xe0, 0xe8, 0x01, 0x10, 0x00, 0x00, +0xfe, 0xfa, 0xfa, 0xfe, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x7d, 0xef, 0x10, 0x84, 0x4d, 0x45, 0xe5, 0xa5, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xff, 0xff, 0x10, 0x84, 0x94, 0x14, 0xb4, 0x00, 0xdf, 0xff, 0xef, 0x7b, +0x57, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x8c, 0xf8, 0x6b, 0xf0, 0xea, 0xea, 0xea, 0xea, 0x8c, 0xf0, 0x6b, 0xf0, +0xff, 0xff, 0xff, 0xfb, 0x6b, 0xf0, 0x6b, 0xe0, 0xea, 0xfa, 0xea, 0xfa, +0x6b, 0xe8, 0x6a, 0xd8, 0xfa, 0xfa, 0xfa, 0xfa, 0x6a, 0xd8, 0x6a, 0xd0, +0xe0, 0xe0, 0xa0, 0xe0, 0x6a, 0xd0, 0x69, 0xc8, 0x70, 0xe8, 0x78, 0xe8, +0x6a, 0xd0, 0x69, 0xc0, 0x5f, 0x5f, 0x5f, 0x5f, 0x69, 0xc0, 0x48, 0xb0, +0xfe, 0xfe, 0xfa, 0x7a, 0x68, 0xb0, 0x48, 0xa8, 0x7a, 0x7a, 0x7e, 0x7a, +0x48, 0xa8, 0x47, 0x98, 0xfa, 0xfa, 0xfa, 0xfa, 0x47, 0x90, 0x47, 0x98, +0x09, 0x09, 0x09, 0x09, 0x47, 0x90, 0x46, 0x80, 0x7a, 0x7a, 0x7e, 0x7e, +0x46, 0x80, 0x25, 0x70, 0xe8, 0xe8, 0xe8, 0xe8, 0x45, 0x70, 0x25, 0x68, +0x78, 0x78, 0x78, 0x78, 0x25, 0x68, 0x24, 0x58, 0xfa, 0xfa, 0xfa, 0xfa, +0x24, 0x58, 0x24, 0x50, 0x78, 0x78, 0x78, 0x78, 0x24, 0x50, 0x23, 0x40, +0xfa, 0xfa, 0xfa, 0xfa, 0x23, 0x40, 0x23, 0x38, 0x78, 0x78, 0x78, 0x78, +0x23, 0x38, 0x02, 0x28, 0xea, 0xfa, 0xea, 0xea, 0x22, 0x30, 0x02, 0x20, +0xfa, 0xfa, 0xfa, 0xfe, 0x22, 0x28, 0x01, 0x18, 0xfe, 0xfe, 0xfe, 0x7e, +0x01, 0x18, 0x01, 0x10, 0xe8, 0xe8, 0xf8, 0xe8, 0x01, 0x10, 0x00, 0x08, +0xa8, 0xe8, 0xa0, 0xa8, 0x01, 0x10, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x10, 0x84, +0xb5, 0x15, 0x95, 0x00, 0xff, 0xff, 0x10, 0x84, 0x15, 0x15, 0x17, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, +0x00, 0x44, 0x44, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x41, 0x08, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0xbe, 0xf7, 0x10, 0x84, 0x00, 0x14, 0x14, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x6c, 0x78, 0x78, 0x50, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x30, 0x84, +0x1e, 0x1b, 0x1b, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xdf, 0xff, 0x10, 0x84, 0x50, 0x50, 0x58, 0x58, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x30, 0x84, 0x11, 0x11, 0x39, 0x39, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x42, +0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0xff, 0xff, 0x08, 0x42, 0x2b, 0x2b, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xa2, 0x10, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x04, 0x21, 0xbe, 0xf7, +0x55, 0x5a, 0x5a, 0x5a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xff, 0xff, 0x28, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, +0xde, 0xff, 0xc8, 0x88, 0xff, 0xff, 0xff, 0xff, 0xde, 0xff, 0xc8, 0x88, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x71, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x39, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x49, 0x4a, 0x0f, 0x0f, 0x0f, 0x0f, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0x28, 0x42, +0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x10, 0x84, 0xdf, 0xff, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xa2, 0x10, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xd3, 0x9d, 0x02, 0x10, +0xff, 0xff, 0xff, 0xff, 0xd3, 0x9d, 0x02, 0x10, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xbe, 0xf7, 0xaa, 0x52, +0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0x08, 0x42, 0x00, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x08, 0x42, 0x00, 0x2b, 0x2b, 0x2b, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0x10, 0x84, +0x58, 0x58, 0x50, 0x50, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xdf, 0xff, 0x30, 0x84, 0x39, 0x39, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x50, 0x78, 0x78, 0x6c, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf7, 0x30, 0x84, +0x11, 0x1b, 0x1b, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xbe, 0xf7, 0x30, 0x84, 0x4c, 0x44, 0x44, 0x00, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x41, 0x08, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0xbe, 0xf7, 0x10, 0x84, 0x1c, 0x14, 0x14, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xff, 0xff, 0x10, 0x84, +0x00, 0xb4, 0x14, 0x94, 0xdf, 0xff, 0xef, 0x7b, 0x00, 0x55, 0x55, 0x57, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0x10, 0x84, 0x00, 0x95, 0x15, 0xb5, +0xff, 0xff, 0x10, 0x84, 0x00, 0x17, 0x15, 0x15, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xdf, 0xff, 0x10, 0x84, 0x94, 0xd4, 0x54, 0x54, +0x3c, 0xe7, 0xef, 0x7b, 0x56, 0x54, 0x54, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x7d, 0xef, 0x10, 0x84, 0xa5, 0xe5, 0x45, 0x4d, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0x5d, 0xef, 0x10, 0x84, +0x5a, 0x53, 0x51, 0x79, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x10, 0x84, +0x69, 0x71, 0x51, 0x5b, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x30, 0x84, 0x6d, 0x45, 0xe5, 0x00, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, +0xd6, 0xb5, 0x21, 0x08, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xb5, 0x21, 0x08, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x10, 0x84, +0x55, 0x55, 0xd5, 0x00, 0xff, 0xff, 0x10, 0x84, 0x5e, 0x54, 0x56, 0x00, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0xff, 0xff, 0xef, 0x7b, 0x00, 0x95, 0xd5, 0x55, 0xbe, 0xf7, 0x10, 0x84, +0x00, 0x57, 0x54, 0x5c, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0xbe, 0xf7, 0x10, 0x84, 0x00, 0xb5, 0xc5, 0x4d, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x30, 0x84, 0x5a, 0x51, 0x79, 0x4d, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xfc, 0xfc, +0x9e, 0xf7, 0x30, 0x84, 0x69, 0x51, 0x5b, 0x5c, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x3c, 0xe7, 0x69, 0x4a, 0x8f, 0x2f, 0x3f, 0xbf, 0xff, 0xff, 0xef, 0x7b, +0x15, 0x15, 0x17, 0x16, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x10, 0x84, 0xd4, 0x94, 0x34, 0xe4, 0x1c, 0xe7, 0x69, 0x4a, +0xfc, 0xfe, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x08, 0x42, +0xff, 0xff, 0xff, 0x00, 0xdf, 0xff, 0x71, 0x8c, 0x14, 0x1b, 0x11, 0x00, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x51, 0x8c, +0x44, 0x78, 0x50, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0xff, 0xff, 0x10, 0x84, 0x00, 0x35, 0x15, 0x15, 0xbe, 0xef, 0xb0, 0x4c, +0x55, 0x55, 0x57, 0x54, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x5b, 0xe7, 0x29, 0x7c, +0xd5, 0x15, 0x35, 0xc5, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x9d, 0xe7, 0xd0, 0x54, 0x5a, 0x51, 0x69, 0xc5, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x52, 0x70, 0xa5, +0xaa, 0xaa, 0xaa, 0x6a, 0x3a, 0xe7, 0x6a, 0x84, 0x49, 0x51, 0x58, 0x54, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x9d, 0xef, 0xb0, 0x4c, 0x35, 0x95, 0x55, 0x55, 0x9d, 0xef, 0xd0, 0x4c, +0x55, 0x56, 0x5c, 0x53, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x9d, 0xef, 0x49, 0x84, 0x15, 0xa5, 0x4d, 0x71, +0x2e, 0x9d, 0xa6, 0x6b, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x9d, 0xe7, 0xb0, 0x4c, 0x69, 0xc5, 0x35, 0x95, +0x3c, 0xd7, 0xaf, 0x4c, 0x55, 0x55, 0x57, 0x54, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x7c, 0xef, 0xc0, 0x4a, 0xff, 0xbf, 0x3f, 0x8f, +0x9c, 0xef, 0x29, 0x7c, 0x5a, 0x54, 0x57, 0x55, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xb0, 0x4c, 0xb0, 0x44, 0x2a, 0xaa, 0xaa, 0xaa, 0xbe, 0xef, 0xb0, 0x4c, +0x5a, 0x71, 0xcd, 0x35, 0x6e, 0x3c, 0xf1, 0x5c, 0xaa, 0xaa, 0xaa, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x7c, 0xef, 0x29, 0x7c, 0x55, 0x55, 0xd5, 0x15, +0xbd, 0xf7, 0x49, 0x7c, 0x69, 0x53, 0x5c, 0x57, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x7d, 0xe7, 0xb0, 0x4c, 0x95, 0x55, 0x55, 0x55, +0x3b, 0xd7, 0xd0, 0x4c, 0x54, 0x50, 0x61, 0x85, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x3a, 0xe7, 0x49, 0x84, 0x85, 0x41, 0x52, 0x54, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xe7, 0x8f, 0x44, +0x35, 0xd5, 0x55, 0x55, 0xde, 0xf7, 0xef, 0x7b, 0x54, 0x5c, 0x70, 0xcc, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x2c, 0x63, 0xd3, 0x9c, 0xaa, 0xaa, 0xaa, 0x6a, +0xde, 0xf7, 0xef, 0x7b, 0x35, 0x0d, 0x33, 0x1c, 0x70, 0xad, 0x85, 0x63, +0xfe, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xdf, 0xff, 0x10, 0x84, 0x34, 0xd4, 0x54, 0x00, 0xde, 0xf7, 0xef, 0x7b, +0x57, 0x5c, 0x73, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xde, 0xf5, 0x14, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, +0xff, 0xff, 0xff, 0xff, 0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, +0xc0, 0xf5, 0x00, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x14, 0x06, 0xde, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x14, 0x06, 0xde, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, +0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x06, 0xc0, 0x05, 0xaa, 0xaa, 0xaa, 0xaa, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x1e, 0xf0, 0x14, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, +0x00, 0xf0, 0x00, 0xa0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0x00, 0xa0, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, +0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x14, 0x00, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0xde, 0xf7, 0xef, 0x7b, 0x35, 0xcd, 0x73, 0x00, 0xff, 0xff, 0x10, 0x84, +0x17, 0x15, 0x15, 0x00, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x7e, 0xef, 0xd6, 0x63, 0x35, 0xd5, 0x55, 0x55, +0x3d, 0xe7, 0x17, 0x6c, 0x57, 0x58, 0x61, 0x05, 0xd8, 0x8c, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x57, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0xfd, 0xde, 0x93, 0x32, 0xff, 0xff, 0xff, 0x3f, +0x9e, 0xef, 0x37, 0x6c, 0x35, 0x49, 0x52, 0x56, 0xf6, 0x63, 0xfb, 0xb5, +0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x9e, 0xef, 0xf6, 0x63, +0x95, 0x55, 0x55, 0x55, 0x5e, 0xe7, 0x16, 0x6c, 0x5c, 0x73, 0x8d, 0x15, +0x41, 0x08, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x15, 0x25, +0x9e, 0xef, 0x36, 0x6c, 0x85, 0x73, 0x5c, 0x55, 0x16, 0x6c, 0xf6, 0x63, +0x57, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x16, 0x6c, 0xf6, 0x63, 0xd5, 0x55, 0x55, 0x55, 0xbe, 0xf7, 0x10, 0x84, +0x70, 0x8c, 0x94, 0x54, 0x7d, 0xef, 0x10, 0x84, 0x55, 0x55, 0x5c, 0x63, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0x71, 0x8c, 0xcf, 0x7b, +0xff, 0xff, 0xff, 0xbf, 0x9d, 0xef, 0x10, 0x84, 0x55, 0x95, 0x8d, 0x72, +0xbe, 0xf7, 0x10, 0x84, 0x23, 0x1c, 0x15, 0x15, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xd5, 0x0a, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0xde, 0xf7, 0x10, 0x84, 0x25, 0xd5, 0x55, 0x00, 0xbe, 0xf7, 0x30, 0x84, +0x57, 0x58, 0xc9, 0x00, 0xff, 0xff, 0x08, 0x42, 0x3f, 0x3f, 0x3f, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x08, 0x42, +0xfc, 0xfc, 0xbc, 0x00, 0xbe, 0xf7, 0x10, 0x84, 0x35, 0xc9, 0x58, 0x00, +0xff, 0xff, 0x10, 0x84, 0x56, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xf6, 0x63, 0x55, 0x55, 0x55, 0x55, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, +0xff, 0xff, 0xff, 0xff, 0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, +0xda, 0xfd, 0x60, 0x3b, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0xff, 0xff, 0x08, 0x42, 0x00, 0x2f, 0x3f, 0x3f, 0xff, 0xff, 0x8a, 0x52, +0x00, 0xfc, 0xe0, 0x2c, 0xdf, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x56, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0xdf, 0xff, 0x30, 0x84, 0x00, 0x55, 0x55, 0x25, 0xff, 0xff, 0x8a, 0x52, +0x00, 0x2f, 0x22, 0x3e, 0xff, 0xff, 0x08, 0x42, 0x00, 0xfc, 0xfc, 0xfc, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0x55, 0xa9, 0xa9, 0xa9, 0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0x55, 0xa9, 0xa9, 0xa9, +0x00, 0x00, 0xff, 0xff, 0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, +0x55, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0xff, 0xff, 0x55, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x41, 0x08, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0x9e, 0xf7, 0x10, 0x84, 0xe2, 0x35, 0x55, 0x55, 0x3c, 0xe7, 0x10, 0x84, +0x55, 0x5c, 0x83, 0xb5, 0xff, 0xff, 0x30, 0x84, 0x15, 0x15, 0x15, 0x38, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xde, 0xf7, 0x30, 0x84, 0x54, 0x54, 0x94, 0x88, +0x5c, 0xe7, 0x10, 0x84, 0xd5, 0x0d, 0x70, 0x57, 0xbe, 0xf7, 0x30, 0x84, +0x62, 0x57, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x10, 0x84, 0x2d, 0x15, 0x15, 0x15, 0xff, 0xff, 0x30, 0x84, +0x5c, 0x88, 0xd4, 0x54, 0xff, 0xff, 0x10, 0x84, 0x55, 0x57, 0xe2, 0xb5, +0x9d, 0xef, 0x30, 0x84, 0x55, 0x55, 0x55, 0xe0, 0x41, 0x08, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0xff, 0xff, 0x30, 0x84, 0x54, 0x54, 0x54, 0xd4, +0x9d, 0xef, 0x30, 0x84, 0x55, 0x55, 0xd5, 0x82, 0xff, 0xff, 0x10, 0x84, +0x55, 0xb5, 0xe2, 0x57, 0xff, 0xff, 0x30, 0x84, 0x2d, 0x38, 0x15, 0x15, +0xff, 0xff, 0x10, 0x84, 0x5c, 0x54, 0x54, 0x54, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, +0xff, 0xff, 0xff, 0xff, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0xa9, 0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, +0xfb, 0xdf, 0x0a, 0x52, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xff, 0xff, 0x30, 0x84, +0xb5, 0x55, 0x55, 0x00, 0xde, 0xf7, 0x30, 0x84, 0x20, 0x35, 0x15, 0x00, +0xdf, 0xff, 0x30, 0x84, 0x54, 0x80, 0xd4, 0x00, 0xde, 0xf7, 0x30, 0x84, +0x55, 0x7e, 0x2b, 0x00, 0xdf, 0xff, 0x10, 0x84, 0x55, 0x55, 0xa0, 0x00, +0xef, 0x7b, 0xdf, 0xff, 0x40, 0x40, 0x6a, 0x55, 0x82, 0x10, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0xff, 0xff, 0x28, 0x42, 0xff, 0xff, 0xff, 0x00, +0x21, 0x08, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0xc3, 0x18, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0xff, 0xff, 0x08, 0x42, 0xfc, 0xfc, 0xa8, 0x00, +0xde, 0xf7, 0x30, 0x84, 0x55, 0x55, 0x02, 0x00, 0xff, 0xff, 0x10, 0x84, +0x55, 0xaf, 0xfa, 0x00, 0xdf, 0xff, 0x30, 0x84, 0x35, 0x20, 0x15, 0x00, +0xde, 0xf7, 0x30, 0x84, 0x80, 0x54, 0x54, 0x00, 0xff, 0xff, 0x30, 0x84, +0x57, 0x55, 0x55, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, +0xa9, 0xa9, 0xa9, 0x55, 0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0x6a, 0x6a, 0x6a, 0x55, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xa9, 0xa9, 0x55, +0x00, 0x00, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, +0xaa, 0xaa, 0xaa, 0x55, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x6a, 0x6a, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, +0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55, +0x00, 0x00, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55 \ No newline at end of file diff --git a/contrib/single_file_decoder/examples/testcard-zstd.inl b/contrib/single_file_decoder/examples/testcard-zstd.inl new file mode 100644 index 00000000000..9e4388365c1 --- /dev/null +++ b/contrib/single_file_decoder/examples/testcard-zstd.inl @@ -0,0 +1,261 @@ +0x28, 0xb5, 0x2f, 0xfd, 0x60, 0x00, 0x7f, 0x6d, 0x61, 0x00, 0x0a, 0x66, +0xec, 0x17, 0x48, 0x60, 0x1c, 0x5a, 0xc9, 0x5d, 0x1a, 0x38, 0x07, 0xe8, +0xc5, 0x82, 0x99, 0x68, 0xe6, 0x95, 0x45, 0x58, 0x0d, 0x0c, 0xf3, 0x36, +0xc8, 0xd9, 0x0f, 0x46, 0x2d, 0x68, 0x11, 0xf8, 0x31, 0x10, 0xa1, 0x1a, +0x2f, 0x99, 0x5c, 0x84, 0xfd, 0x92, 0x02, 0xe6, 0x3b, 0x44, 0x9b, 0x01, +0x5d, 0x92, 0xff, 0x38, 0x26, 0x00, 0x6a, 0x6b, 0xc3, 0x53, 0xb2, 0x0c, +0x25, 0xf3, 0xd8, 0x59, 0x68, 0x9b, 0x14, 0x8a, 0x89, 0x75, 0x18, 0x03, +0x1d, 0xc9, 0x0f, 0x63, 0x01, 0x73, 0x01, 0x72, 0x01, 0x4f, 0x66, 0x31, +0x58, 0x0f, 0x97, 0x4b, 0x0c, 0x4c, 0x06, 0xac, 0x07, 0x0b, 0x68, 0xd4, +0xad, 0x80, 0x64, 0x13, 0x74, 0xa1, 0x12, 0x16, 0x58, 0xcf, 0x1a, 0x95, +0x5f, 0x0d, 0x26, 0x55, 0xd0, 0x9c, 0xf4, 0x52, 0x35, 0x2e, 0x20, 0xc1, +0x06, 0x69, 0x03, 0x0a, 0x93, 0x83, 0x5e, 0x27, 0x9b, 0x4c, 0x6d, 0xee, +0x87, 0x03, 0x30, 0x6c, 0x46, 0xd7, 0x50, 0x5c, 0xca, 0xe6, 0xa6, 0x4d, +0xa8, 0xf6, 0xab, 0xd7, 0x0e, 0x27, 0x27, 0x90, 0xc4, 0xb2, 0xd1, 0x10, +0xfa, 0x43, 0x82, 0xc8, 0xf2, 0xe5, 0xff, 0xff, 0xd5, 0x52, 0x62, 0x43, +0x87, 0x26, 0x2a, 0x05, 0x70, 0x0e, 0xb0, 0x2f, 0xc4, 0x56, 0xef, 0xb5, +0xca, 0xb8, 0x53, 0xb7, 0x96, 0x0e, 0xe7, 0x00, 0x2c, 0xa8, 0xda, 0x3b, +0x07, 0x70, 0xa7, 0x78, 0x38, 0x60, 0x87, 0x7a, 0x01, 0x3b, 0x75, 0xec, +0xfa, 0x77, 0xe2, 0x46, 0x94, 0x61, 0x8e, 0x0d, 0x0c, 0xfb, 0xe7, 0x8b, +0x13, 0x50, 0x31, 0xa9, 0x27, 0xcd, 0x27, 0xef, 0x6b, 0xa6, 0xab, 0x9c, +0x4d, 0x95, 0x6c, 0x3a, 0xbb, 0x8e, 0x96, 0x92, 0x18, 0x5a, 0x7c, 0x4f, +0xff, 0x7b, 0x38, 0xf2, 0xdb, 0x86, 0xde, 0xff, 0x1f, 0x2f, 0x21, 0x86, +0x7d, 0xbf, 0x45, 0xd0, 0x6e, 0x77, 0x0a, 0xee, 0x0a, 0xee, 0x14, 0x9a, +0xb8, 0x84, 0xf3, 0xac, 0xbe, 0xc8, 0x7f, 0x8d, 0xff, 0xff, 0xcf, 0x2a, +0xfb, 0x69, 0xfc, 0xfb, 0xfd, 0x7a, 0x10, 0x22, 0x36, 0xfc, 0xff, 0x3f, +0xcf, 0xd0, 0xf1, 0x7f, 0xfe, 0xff, 0x3d, 0x24, 0xdf, 0x78, 0x4a, 0xff, +0xda, 0x9c, 0x39, 0xcf, 0xef, 0xe7, 0xfd, 0x52, 0x98, 0xb5, 0x40, 0x92, +0xee, 0xdd, 0x99, 0xf5, 0x53, 0x5b, 0x65, 0x6b, 0xb5, 0xd8, 0x7b, 0xae, +0xfa, 0xc1, 0x0f, 0x0c, 0x7f, 0x4f, 0x55, 0xa3, 0xad, 0x2c, 0xa0, 0xbd, +0xf7, 0x2a, 0x0e, 0xe8, 0xbd, 0xc7, 0x5e, 0xf5, 0xd8, 0x54, 0x9e, 0x56, +0xa3, 0xd6, 0x59, 0xd5, 0xfe, 0x1f, 0xc0, 0x30, 0x8c, 0xfc, 0x46, 0x04, +0xae, 0x60, 0xbc, 0xe8, 0xcf, 0xec, 0x3d, 0xde, 0xf9, 0xf0, 0xfe, 0xef, +0x7d, 0xcc, 0xf7, 0x2b, 0xe5, 0x1b, 0x70, 0xff, 0xff, 0x7e, 0x3f, 0x6e, +0xe4, 0x02, 0x07, 0xfc, 0x1b, 0x7a, 0xff, 0xe7, 0x58, 0xfc, 0x7e, 0x3a, +0xdc, 0x97, 0xfd, 0x57, 0xef, 0xa3, 0xfc, 0x2a, 0xc7, 0x4d, 0xf3, 0xcb, +0x9d, 0xce, 0xac, 0xfe, 0xeb, 0x2e, 0x86, 0xb9, 0x69, 0x54, 0xef, 0xf9, +0x55, 0xcf, 0xff, 0x48, 0x24, 0x72, 0x3a, 0x9d, 0x72, 0x2f, 0x2f, 0x2f, +0xff, 0x3f, 0xe7, 0x01, 0x6c, 0x4d, 0x6c, 0xcd, 0x2d, 0x5b, 0x53, 0xb7, +0x59, 0x22, 0x08, 0x0b, 0xa7, 0x92, 0x15, 0x75, 0x93, 0xb0, 0x5d, 0xaf, +0x2a, 0x63, 0x95, 0x1d, 0x25, 0xd2, 0xd2, 0xa8, 0x1c, 0x84, 0xc9, 0xdc, +0x72, 0xba, 0xd7, 0xfc, 0x69, 0xf5, 0xc7, 0x19, 0xa9, 0xbe, 0xfa, 0x26, +0x55, 0x25, 0x75, 0xb7, 0x60, 0xa3, 0xd8, 0x68, 0x54, 0xb7, 0x1b, 0xa5, +0x54, 0x62, 0xb1, 0x49, 0xde, 0xe2, 0xac, 0xa2, 0xe8, 0x7b, 0xff, 0x5f, +0x75, 0x4e, 0xb8, 0xa2, 0xdd, 0x6a, 0xb7, 0xda, 0x6e, 0x2e, 0x04, 0xcd, +0x08, 0x2f, 0xec, 0x8e, 0x49, 0xaf, 0x49, 0x6f, 0x8b, 0x4f, 0x2e, 0x1a, +0xc5, 0x62, 0x7b, 0x6b, 0x3e, 0x32, 0x3e, 0x32, 0xbe, 0x08, 0x35, 0x4d, +0x63, 0x93, 0xa6, 0xc8, 0x42, 0xe6, 0x21, 0xcc, 0x59, 0xc8, 0x4c, 0xe5, +0x86, 0xe1, 0x03, 0x06, 0xa4, 0xec, 0xff, 0xb7, 0x78, 0x7e, 0x62, 0x43, +0xc7, 0x2c, 0x50, 0x30, 0x4a, 0xc8, 0x9b, 0xf3, 0xbf, 0xe6, 0x62, 0xa0, +0x50, 0xa6, 0x9c, 0xe3, 0x6e, 0x5b, 0xaf, 0x77, 0x8b, 0xbb, 0xe1, 0x70, +0xaa, 0xaa, 0xaa, 0x92, 0xb4, 0x52, 0xad, 0x14, 0x87, 0x93, 0x0b, 0xe6, +0x82, 0x39, 0x11, 0xb9, 0x20, 0x9a, 0x16, 0x34, 0x22, 0x68, 0xb2, 0x68, +0xb2, 0x76, 0xd3, 0xe8, 0x6e, 0xda, 0x6b, 0x62, 0x34, 0x2e, 0x8d, 0xbd, +0x2d, 0x3d, 0x6b, 0x4c, 0x26, 0x33, 0xda, 0x33, 0xf3, 0x91, 0x51, 0x46, +0x79, 0xbd, 0x3e, 0x39, 0x9f, 0xcf, 0xd2, 0xb8, 0x5c, 0xfa, 0x22, 0xf8, +0x8e, 0xb6, 0xbe, 0x08, 0x40, 0x14, 0x49, 0x40, 0x14, 0xf2, 0x0c, 0x2d, +0x30, 0x85, 0x3c, 0x63, 0x29, 0xd3, 0x98, 0x85, 0x6c, 0xb5, 0xdb, 0xad, +0x5c, 0x63, 0x9e, 0x72, 0xcf, 0x43, 0xe6, 0xaf, 0x77, 0xa6, 0xe2, 0x21, +0x0c, 0x4d, 0xd3, 0x49, 0x1e, 0xc2, 0x14, 0x6f, 0xee, 0xdb, 0x7b, 0x7b, +0x08, 0xb3, 0xa4, 0x60, 0x3b, 0x9d, 0x6e, 0x8b, 0x37, 0x4b, 0x0a, 0x74, +0x35, 0x33, 0xbc, 0xf9, 0x64, 0x85, 0x63, 0x32, 0x29, 0x20, 0x59, 0x0c, +0x3c, 0x96, 0x67, 0x62, 0xb7, 0x8a, 0x92, 0x4d, 0xa0, 0xd3, 0xf3, 0xd1, +0x85, 0x80, 0x38, 0xcb, 0x64, 0x60, 0xc9, 0xb5, 0xaf, 0x97, 0x8d, 0x20, +0x45, 0x28, 0xb8, 0xab, 0xe8, 0xc9, 0x0a, 0x88, 0x1f, 0xd6, 0x47, 0x54, +0xf1, 0xd3, 0xfb, 0x62, 0xa7, 0xfd, 0xf2, 0x8b, 0xfd, 0xb6, 0xe4, 0x2e, +0xb6, 0x91, 0x73, 0x1c, 0xd0, 0x7b, 0xba, 0x83, 0xc9, 0xac, 0x51, 0x39, +0x92, 0xc5, 0x4f, 0x30, 0x1e, 0x2e, 0xd5, 0xf1, 0xa8, 0xa6, 0xa5, 0x80, +0x70, 0xb9, 0xbc, 0xb7, 0xc2, 0x52, 0x32, 0x6c, 0xe3, 0x3d, 0xed, 0x41, +0xa4, 0x4b, 0x31, 0x2a, 0xe6, 0x62, 0x11, 0x19, 0x95, 0x73, 0x1d, 0xbf, +0xe1, 0x6c, 0xfc, 0x47, 0x75, 0x6c, 0x37, 0x63, 0x02, 0xf8, 0x34, 0x40, +0x9a, 0x00, 0x1d, 0xf7, 0x32, 0x56, 0x77, 0xda, 0x5b, 0x9f, 0x9f, 0x0f, +0xbb, 0x91, 0x5b, 0xbd, 0xe7, 0x58, 0x82, 0x4a, 0x20, 0xcd, 0x4f, 0x47, +0x15, 0xf3, 0x51, 0xf1, 0x43, 0x51, 0x10, 0x96, 0xae, 0xba, 0xf7, 0x21, +0x50, 0xef, 0x55, 0x27, 0x0c, 0x1f, 0xe0, 0x54, 0xf8, 0xc9, 0x69, 0xef, +0xb9, 0x53, 0xf7, 0x83, 0x73, 0x9d, 0xce, 0x86, 0x07, 0x83, 0x44, 0x61, +0x37, 0x35, 0x35, 0x33, 0x4e, 0x33, 0x33, 0x3e, 0x9f, 0x50, 0x48, 0x24, +0xe6, 0xd0, 0x79, 0x49, 0xc3, 0x2d, 0xa0, 0x46, 0x31, 0x9a, 0x72, 0xc3, +0x84, 0xff, 0x7a, 0x95, 0xbb, 0x00, 0x22, 0xcc, 0x14, 0x00, 0x04, 0xac, +0x60, 0x64, 0x86, 0xe4, 0x6f, 0xb1, 0x58, 0xf4, 0xdc, 0xb0, 0x05, 0x00, +0x72, 0x38, 0xf8, 0xce, 0xce, 0x8e, 0xcf, 0x37, 0x33, 0x43, 0x24, 0x0a, +0x85, 0x33, 0x35, 0x35, 0x37, 0xc2, 0xa8, 0x28, 0x27, 0x1b, 0x9d, 0xce, +0x29, 0x18, 0xe4, 0xfc, 0x09, 0x53, 0xa5, 0x51, 0xad, 0x74, 0x79, 0x7b, +0xb5, 0x4a, 0x65, 0x94, 0x36, 0x89, 0xf5, 0x62, 0x9b, 0xd8, 0x9a, 0xe8, +0x2b, 0xff, 0xa1, 0x73, 0xfe, 0x2e, 0x2c, 0x41, 0x45, 0x37, 0xef, 0x6e, +0x7b, 0x38, 0xca, 0xa5, 0xd2, 0xb8, 0x1c, 0x3b, 0x96, 0x21, 0xbb, 0x5d, +0xad, 0xd1, 0xdb, 0x1c, 0xf6, 0x5e, 0x4b, 0xd9, 0x59, 0x1b, 0x67, 0xf5, +0x7a, 0x7c, 0x9a, 0x91, 0x3e, 0x8e, 0xe3, 0xee, 0x7b, 0xb9, 0xa4, 0xb9, +0xf5, 0x70, 0xee, 0x1d, 0x4e, 0x4f, 0xcc, 0xd6, 0x7b, 0x07, 0x71, 0x48, +0xf2, 0x06, 0xd0, 0x10, 0x82, 0x21, 0xe4, 0x55, 0x2e, 0xa5, 0x1d, 0xbe, +0x48, 0x8c, 0x69, 0xbb, 0x24, 0x40, 0x68, 0x9b, 0xba, 0x5a, 0x5a, 0xa7, +0xe2, 0xd1, 0xac, 0xc2, 0xd8, 0x87, 0x9c, 0xe3, 0x78, 0xee, 0xa6, 0xcd, +0xdd, 0x68, 0x6e, 0xdd, 0xdb, 0x2e, 0xc6, 0xbb, 0x8b, 0xe9, 0xc1, 0xd9, +0xf6, 0x62, 0x7e, 0x72, 0x7e, 0x72, 0x34, 0xe4, 0x68, 0xc8, 0x11, 0x32, +0x10, 0x32, 0x20, 0x32, 0xf0, 0x12, 0x19, 0x90, 0xe0, 0x45, 0x91, 0xe0, +0x25, 0x83, 0xba, 0xc9, 0x20, 0x26, 0x87, 0xa5, 0x72, 0xa9, 0x64, 0x72, +0x80, 0x21, 0x54, 0x13, 0xeb, 0x29, 0x18, 0x42, 0x34, 0x84, 0x94, 0x34, +0x84, 0xa4, 0x1d, 0xa4, 0x1d, 0x82, 0x1c, 0xef, 0xaf, 0x0e, 0x63, 0x47, +0x6d, 0x10, 0xb9, 0xec, 0xd8, 0x2d, 0x3b, 0x9e, 0x21, 0xb1, 0x67, 0x48, +0x34, 0x24, 0x1a, 0x52, 0xdb, 0xa4, 0x6d, 0x62, 0xd3, 0xfa, 0xff, 0xfa, +0x03, 0x34, 0xef, 0x9d, 0xc9, 0xe1, 0x5d, 0xec, 0xf5, 0xf1, 0x79, 0x8c, +0x97, 0xd2, 0x24, 0xc1, 0x2d, 0xe0, 0x39, 0x16, 0x1e, 0xa9, 0x41, 0xc3, +0xbf, 0x4a, 0xd9, 0x3c, 0xea, 0x77, 0x96, 0x55, 0xe6, 0x95, 0xc3, 0xf1, +0x8e, 0x7b, 0x4f, 0xad, 0x61, 0xf8, 0xe7, 0x01, 0xad, 0x46, 0xf5, 0x2c, +0xac, 0x55, 0x2c, 0x94, 0xaa, 0x46, 0xfb, 0x5e, 0xcd, 0xaa, 0x1f, 0x78, +0x4f, 0x2f, 0xd1, 0xc9, 0x02, 0xd6, 0x2c, 0x67, 0xef, 0x3f, 0x54, 0xab, +0xda, 0x03, 0x79, 0x1f, 0xab, 0xfd, 0x0c, 0x38, 0x3c, 0xbc, 0xe1, 0xd5, +0x01, 0xf6, 0xfb, 0xfb, 0xf1, 0x70, 0xee, 0xfd, 0x90, 0x13, 0x97, 0xc4, +0xbc, 0x08, 0xe7, 0x4b, 0x88, 0x34, 0xf7, 0x56, 0x1e, 0x0c, 0xdb, 0xe4, +0x9c, 0x78, 0xf1, 0xf4, 0x62, 0x4c, 0xb5, 0xf7, 0xdd, 0xd9, 0x4c, 0x5a, +0x69, 0xa6, 0x36, 0x27, 0x03, 0xbe, 0x86, 0xc2, 0x72, 0xa2, 0x60, 0x73, +0xf1, 0xe0, 0x17, 0x50, 0xb5, 0x93, 0x81, 0xac, 0xf1, 0xc9, 0xd4, 0x66, +0x73, 0x71, 0xce, 0x63, 0xa8, 0x60, 0x98, 0xda, 0x86, 0x46, 0x72, 0xec, +0x54, 0xc1, 0xe6, 0x8a, 0x10, 0x23, 0x2d, 0x0c, 0xdd, 0x44, 0x0b, 0xa0, +0x44, 0xa4, 0x9d, 0x0e, 0x64, 0x31, 0x30, 0x45, 0xb1, 0x97, 0x4c, 0x6d, +0x9f, 0x43, 0x99, 0x71, 0xa8, 0x9a, 0xe6, 0xbd, 0x3a, 0xe1, 0xff, 0x7f, +0x33, 0x61, 0xf1, 0x48, 0xda, 0x48, 0x28, 0x10, 0x23, 0x9b, 0x24, 0xeb, +0xee, 0xbd, 0x35, 0x0e, 0x6e, 0x75, 0x23, 0x20, 0xd6, 0x95, 0x8c, 0xa5, +0x24, 0xec, 0x44, 0x67, 0x52, 0x2e, 0x78, 0x2a, 0xba, 0x3e, 0x3a, 0x4e, +0xc9, 0x5c, 0x23, 0xb0, 0xd5, 0xfb, 0x29, 0xaf, 0x9a, 0x0b, 0x90, 0x89, +0xd8, 0xec, 0xa9, 0xa8, 0x13, 0xfc, 0x22, 0xfa, 0xf2, 0x74, 0x2f, 0x4e, +0x35, 0xb0, 0x6d, 0x6c, 0xfd, 0xc4, 0xfe, 0xd0, 0x98, 0x3d, 0xe5, 0x43, +0x0a, 0xd0, 0x33, 0x26, 0x3b, 0x12, 0x7d, 0x65, 0xa1, 0xff, 0xff, 0x6f, +0x53, 0x0e, 0x28, 0x84, 0xa7, 0xa2, 0x2e, 0xf8, 0x4a, 0xb6, 0xa1, 0x47, +0xf5, 0xd0, 0x13, 0x9d, 0xd9, 0x50, 0xef, 0x9f, 0x31, 0xb4, 0x13, 0x67, +0xf9, 0x0a, 0x99, 0xb5, 0x80, 0xec, 0x4a, 0x1a, 0x59, 0x21, 0x3b, 0xce, +0xc5, 0x7e, 0x96, 0x85, 0x92, 0xc5, 0xb0, 0x75, 0xaa, 0x41, 0x16, 0xa9, +0xd3, 0xde, 0x13, 0x7d, 0xd9, 0x61, 0x30, 0x1c, 0x73, 0x61, 0x54, 0x90, +0xcf, 0xd4, 0xe8, 0xfe, 0xbf, 0xbf, 0x36, 0x57, 0x26, 0x38, 0xab, 0x06, +0xc4, 0x7e, 0x3c, 0x5b, 0x35, 0xd2, 0x7c, 0x2c, 0x0a, 0x82, 0xf2, 0xa8, +0xf2, 0x8b, 0x48, 0xa9, 0x90, 0x00, 0x01, 0x10, 0x10, 0x14, 0x04, 0x00, +0x32, 0xa2, 0x06, 0x82, 0x28, 0x90, 0xc2, 0xb4, 0x85, 0xda, 0x01, 0x52, +0xe9, 0x18, 0x85, 0x60, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x14, 0x41, 0x00, +0x40, 0xa0, 0x04, 0x40, 0x00, 0x80, 0x50, 0x03, 0x01, 0x10, 0x18, 0x01, +0x80, 0xd4, 0x14, 0x99, 0x01, 0xfd, 0x07, 0xf8, 0x16, 0x0e, 0xd9, 0x5d, +0xa3, 0x70, 0xfe, 0xda, 0x17, 0xfa, 0xce, 0x46, 0x9a, 0x99, 0x81, 0x1a, +0x39, 0xba, 0x63, 0xb1, 0x18, 0x11, 0x58, 0xd7, 0xc7, 0xba, 0x03, 0x3e, +0x01, 0xf2, 0xf9, 0x4e, 0x12, 0xa3, 0x50, 0x7b, 0xaf, 0x7b, 0x60, 0x5c, +0x83, 0x23, 0xd2, 0x60, 0x27, 0x84, 0xad, 0xb8, 0x02, 0xed, 0xfe, 0xb4, +0x9c, 0x08, 0x9f, 0x49, 0xae, 0x55, 0x02, 0x94, 0xc0, 0x1b, 0x90, 0x75, +0x0b, 0x90, 0xc4, 0xc7, 0x43, 0x9e, 0x67, 0x25, 0x70, 0x61, 0x0d, 0xb8, +0x7a, 0x97, 0x43, 0xfc, 0xd1, 0x7e, 0x68, 0xed, 0x03, 0xb7, 0x1e, 0x75, +0xe9, 0x4d, 0x7a, 0x23, 0x18, 0x37, 0x63, 0x6f, 0xab, 0x5f, 0x7c, 0x5b, +0x1c, 0x05, 0xdf, 0x3f, 0x00, 0x86, 0x37, 0xa0, 0xfa, 0x0c, 0xe0, 0xed, +0x35, 0x35, 0x2f, 0xd8, 0xd1, 0x75, 0xba, 0x37, 0x34, 0x7e, 0xb0, 0x84, +0x2a, 0x01, 0x0c, 0x98, 0xed, 0x47, 0xf9, 0x86, 0x81, 0x74, 0x00, 0x5d, +0x8b, 0x4c, 0x18, 0x8a, 0x31, 0xcd, 0xae, 0x07, 0x44, 0xb5, 0xd5, 0x07, +0xa0, 0xdf, 0xf4, 0xfa, 0xa6, 0x42, 0xd0, 0x4f, 0x17, 0xd8, 0xdf, 0xb6, +0x34, 0x44, 0xe3, 0x01, 0xc4, 0xb6, 0x2d, 0xb5, 0x56, 0xc6, 0x2a, 0x1f, +0x05, 0x6c, 0x35, 0xe0, 0x09, 0x31, 0xef, 0x60, 0xfe, 0xaf, 0x07, 0x80, +0x32, 0xa0, 0xe9, 0xd3, 0x96, 0x45, 0xa7, 0xaa, 0xb6, 0xfb, 0x03, 0x10, +0xe3, 0x97, 0x96, 0x8d, 0x3a, 0x01, 0xdd, 0x58, 0x58, 0x78, 0x00, 0xab, +0xff, 0x06, 0xa0, 0xd6, 0x01, 0x58, 0x08, 0xb7, 0xdc, 0x2d, 0xa7, 0xfb, +0x22, 0xa8, 0x67, 0x00, 0xe3, 0xcf, 0x82, 0x43, 0xfc, 0x96, 0x1b, 0x40, +0x63, 0xcf, 0x9d, 0x42, 0x5d, 0x66, 0x40, 0xaa, 0xaf, 0x28, 0x94, 0xd3, +0x2a, 0xd4, 0x02, 0x13, 0xd2, 0xdf, 0x03, 0x9c, 0x60, 0x6b, 0x16, 0x94, +0xb4, 0xbe, 0x62, 0xc2, 0x35, 0x60, 0x45, 0x09, 0x23, 0x5a, 0xe0, 0x85, +0xb3, 0x03, 0x50, 0x68, 0x0c, 0x20, 0xa5, 0xf9, 0x94, 0xd2, 0x35, 0x80, +0xad, 0x4c, 0x4e, 0x40, 0x41, 0x97, 0x92, 0x75, 0xbe, 0x0c, 0x03, 0x50, +0x85, 0x08, 0xaf, 0x36, 0x00, 0x68, 0xaf, 0x09, 0xb3, 0x0c, 0x20, 0x4f, +0x81, 0x6a, 0x6a, 0xf5, 0x0d, 0x70, 0x69, 0x00, 0x4c, 0xb4, 0x0f, 0x59, +0xe7, 0x31, 0x0a, 0x45, 0x9f, 0xde, 0x90, 0xd6, 0x38, 0x80, 0x6b, 0x2c, +0xb9, 0x2f, 0xd4, 0x01, 0x40, 0x14, 0xd5, 0xed, 0x8e, 0x01, 0x53, 0xbf, +0x03, 0x18, 0x1e, 0xb0, 0xc1, 0x85, 0x32, 0xec, 0x78, 0x2b, 0xf0, 0xbb, +0xbb, 0x6c, 0xf3, 0x4d, 0xdc, 0x73, 0x40, 0xfd, 0x10, 0x09, 0x9e, 0x20, +0xe2, 0x12, 0x8c, 0xe0, 0xd2, 0xed, 0x80, 0x6b, 0xcc, 0x78, 0x20, 0x03, +0xd0, 0x5e, 0x06, 0xf4, 0xb0, 0xc4, 0x0e, 0x15, 0x1d, 0x80, 0xb4, 0x76, +0xdf, 0x49, 0x03, 0x50, 0x82, 0xad, 0xda, 0x8b, 0x5a, 0x61, 0xc2, 0x5e, +0xb5, 0x1e, 0x46, 0xc0, 0xde, 0xaa, 0x0e, 0x15, 0x06, 0xd2, 0xf4, 0xb2, +0xd1, 0xed, 0x38, 0x0a, 0x03, 0x18, 0x33, 0x1a, 0x80, 0x61, 0x3e, 0xec, +0x7c, 0x74, 0xa8, 0x1d, 0x80, 0x1a, 0xce, 0x25, 0x1d, 0x41, 0xd1, 0xc1, +0x03, 0x28, 0xb5, 0xaf, 0x72, 0x9c, 0x59, 0x7a, 0xe1, 0x7d, 0xc0, 0xa5, +0x08, 0x1e, 0x18, 0x24, 0xfa, 0xbd, 0x99, 0x4a, 0x31, 0xa0, 0xea, 0xee, +0xf8, 0x36, 0x60, 0x98, 0xc9, 0x10, 0xd1, 0xa7, 0x35, 0x00, 0x8d, 0x40, +0x8e, 0x5a, 0x35, 0x0f, 0x80, 0xb1, 0xd4, 0x32, 0x79, 0x40, 0x34, 0x05, +0x7e, 0x98, 0xc6, 0x80, 0x3e, 0x90, 0x01, 0x65, 0xf4, 0x80, 0x73, 0x08, +0x64, 0xd7, 0x36, 0xc1, 0x7c, 0xc0, 0x5c, 0x75, 0x00, 0xc5, 0x09, 0x58, +0x9c, 0x13, 0x01, 0x72, 0x37, 0x9b, 0x79, 0xe4, 0x05, 0xd1, 0x01, 0x04, +0x98, 0x08, 0x74, 0xfd, 0xfc, 0x3f, 0x1c, 0x00, 0x73, 0x01, 0xfc, 0x1c, +0xcc, 0x16, 0x43, 0x19, 0x1d, 0xac, 0x61, 0x4b, 0x11, 0xc2, 0xa0, 0xf2, +0x01, 0x0b, 0x7b, 0x3b, 0xf4, 0xfc, 0x58, 0x5d, 0x2d, 0x5c, 0x01, 0x8c, +0x62, 0x17, 0x78, 0xbe, 0x60, 0x8c, 0x01, 0x6f, 0x91, 0x49, 0x65, 0x54, +0x92, 0xe9, 0x01, 0x1e, 0x10, 0x77, 0x35, 0x00, 0xa8, 0xd4, 0xc7, 0x71, +0x07, 0xd8, 0xcd, 0xa3, 0x7d, 0x69, 0x20, 0xac, 0x07, 0x00, 0x35, 0xc7, +0x62, 0xee, 0x8c, 0x7d, 0x0c, 0xb8, 0x43, 0x0e, 0x00, 0x08, 0xfb, 0xe7, +0xec, 0x33, 0x37, 0x04, 0x80, 0x2d, 0x1d, 0xa6, 0x13, 0x34, 0x1b, 0x1d, +0xc0, 0xca, 0x00, 0x92, 0xed, 0x2e, 0x56, 0xbe, 0x91, 0x80, 0x0c, 0x88, +0xa6, 0x01, 0xdf, 0x7f, 0x90, 0x49, 0xed, 0x0c, 0xe0, 0x08, 0x73, 0x28, +0x74, 0xc7, 0xe1, 0xb1, 0x03, 0x5d, 0xc5, 0xab, 0x61, 0x42, 0xdf, 0x03, +0x43, 0xf3, 0x35, 0x04, 0xcf, 0xc6, 0x1d, 0x79, 0x07, 0x40, 0x22, 0xe4, +0x68, 0x0d, 0x01, 0x95, 0xad, 0x72, 0x69, 0x00, 0x39, 0x9d, 0x53, 0x8f, +0x13, 0x0d, 0xb0, 0x29, 0x79, 0x1a, 0x39, 0x20, 0x12, 0x28, 0x9b, 0x02, +0x8f, 0x74, 0x90, 0x4c, 0xe8, 0xd1, 0x57, 0xf4, 0x01, 0x44, 0x04, 0xe0, +0x0c, 0x82, 0x91, 0xc5, 0x4f, 0x8f, 0xc6, 0x00, 0x43, 0x85, 0x65, 0xc8, +0xe6, 0x34, 0x1d, 0x80, 0xc0, 0xca, 0xdb, 0x57, 0x6c, 0x00, 0x72, 0x42, +0x5f, 0xd0, 0x49, 0x57, 0x47, 0xd4, 0x97, 0x18, 0x18, 0x80, 0x68, 0x8e, +0x0a, 0xf1, 0x6b, 0x34, 0xf1, 0x60, 0x2c, 0x41, 0x29, 0xd3, 0x3d, 0x55, +0x95, 0xb1, 0x3c, 0xd4, 0x95, 0x42, 0xef, 0xe7, 0xca, 0x00, 0x2e, 0xce, +0x25, 0xc2, 0xca, 0xf5, 0x00, 0x17, 0x3b, 0x8c, 0x42, 0x88, 0x03, 0xde, +0x97, 0xe1, 0x3a, 0x74, 0xb0, 0x33, 0xe0, 0x8f, 0x47, 0xeb, 0x2a, 0x5f, +0x36, 0x3e, 0x5a, 0xff, 0xc5, 0x80, 0xb9, 0x13, 0xa9, 0x1f, 0xf8, 0x86, +0xc9, 0x51, 0xf8, 0x4c, 0xaa, 0xe1, 0x65, 0x80, 0xb0, 0x8b, 0x91, 0xec, +0xcc, 0xbf, 0x70, 0x19, 0x98, 0x03, 0x10, 0xf0, 0x38, 0x40, 0xc4, 0x65, +0xbe, 0x41, 0xb2, 0x58, 0x3f, 0xe0, 0xcc, 0x0e, 0x08, 0x2b, 0x73, 0xf4, +0xdd, 0x86, 0x06, 0xa0, 0xc6, 0x8f, 0x1a, 0x32, 0x66, 0x50, 0x8e, 0xe1, +0x59, 0x67, 0x00, 0xed, 0x66, 0x1d, 0xdd, 0xfa, 0x7b, 0xe2, 0x56, 0x89, +0xd9, 0xa0, 0x4f, 0x41, 0x94, 0x28, 0xb8, 0xc6, 0xc7, 0x64, 0xde, 0x9b, +0x64, 0x44, 0x33, 0x39, 0xb5, 0x6c, 0xb9, 0x42, 0xe7, 0x7e, 0x16, 0xd2, +0x01, 0x12, 0x03, 0xb3, 0x48, 0x47, 0x6b, 0x75, 0x26, 0x19, 0x8c, 0xac, +0x6f, 0xb1, 0x6f, 0xdc, 0x04, 0x27, 0x3a, 0x00, 0xd6, 0xae, 0xfa, 0xe1, +0xf7, 0x30, 0xa4, 0xdb, 0xd5, 0x86, 0x5a, 0x07, 0x11, 0xde, 0xea, 0xf4, +0xb0, 0x83, 0x16, 0xbb, 0xc6, 0x00, 0x6e, 0xf2, 0x6b, 0x40, 0x81, 0x01, +0x67, 0x0e, 0xa9, 0x82, 0x23, 0x04, 0x34, 0xed, 0x02, 0xf5, 0xe4, 0x0e, +0x58, 0xe8, 0x8a, 0x58, 0x57, 0xb0, 0x56, 0x65, 0x3d, 0x40, 0x64, 0x03, +0x6e, 0x7b, 0x07, 0x20, 0x99, 0x90, 0x36, 0x95, 0x9f, 0xdf, 0x3d, 0xe8, +0x00, 0xa0, 0x57, 0x8f, 0x6d, 0xa4, 0xb3, 0x1d, 0x7a, 0x06, 0xa8, 0x26, +0x41, 0xb0, 0x8c, 0x9c, 0x10, 0x85, 0x6c, 0xb4, 0x31, 0xa6, 0x5b, 0x7a, +0x10, 0x51, 0x15, 0x3c, 0xa2, 0x42, 0xd3, 0x23, 0x02, 0xc0, 0x17, 0x7e, +0x03, 0x28, 0xba, 0xce, 0x9b, 0xae, 0xdd, 0x1a, 0x19, 0xd0, 0x15, 0xac, +0xeb, 0x20, 0x3c, 0x3a, 0x00, 0xc6, 0xbb, 0x8a, 0xd5, 0x64, 0xc2, 0x21, +0x1d, 0x6c, 0x15, 0x5a, 0xd3, 0x44, 0x98, 0x14, 0x95, 0xb3, 0xb7, 0xdd, +0xa6, 0xea, 0x06, 0x54, 0x78, 0xc3, 0xe8, 0x79, 0x9b, 0x86, 0x29, 0x76, +0x8b, 0x6b, 0xaa, 0x0d, 0xa8, 0x2f, 0x22, 0x2a, 0xeb, 0x68, 0x81, 0x6c, +0x56, 0xfd, 0x79, 0xac, 0x79, 0x4b, 0xa0, 0x01, 0x3f, 0x17, 0x43, 0x82, +0xb4, 0xd5, 0x00, 0x14, 0xb7, 0xf5, 0x00, 0xf4, 0x15, 0xa8, 0xd7, 0x4b, +0xb1, 0xbc, 0xa8, 0x36, 0x98, 0xf0, 0x8c, 0xe7, 0xf4, 0x7b, 0x35, 0xd8, +0xad, 0x0d, 0x5f, 0x9d, 0x96, 0xab, 0xed, 0x48, 0xe2, 0xdc, 0x1c, 0xbe, +0x12, 0xfa, 0x41, 0x6f, 0xf5, 0x1e, 0xb6, 0x9f, 0xee, 0xac, 0x21, 0xf4, +0xf6, 0x00, 0x38, 0xb1, 0x1f, 0xfd, 0xd0, 0x0e, 0xc7, 0xdd, 0xa0, 0x39, +0x07, 0x8c, 0x35, 0x1f, 0x7e, 0xcc, 0xbf, 0xf6, 0xe0, 0x06, 0x66, 0x7d, +0x10, 0x3f, 0xc5, 0x3e, 0xde, 0x42, 0xf9, 0x3d, 0x00, 0x54, 0x81, 0x67, +0x8a, 0xe6, 0x63, 0x0d, 0x01, 0xd0, 0x31, 0xe0, 0x6e, 0xd0, 0xe1, 0x59, +0xf6, 0x1b, 0xf7, 0x0d, 0x52, 0x06, 0x80, 0x61, 0x4f, 0xe8, 0x77, 0xdd, +0x6f, 0x48, 0x20, 0x1d, 0xbb, 0x2a, 0x16, 0x8b, 0x54, 0x87, 0x92, 0x83, +0xe6, 0x8f, 0x55, 0x59, 0x06, 0x00, 0xe9, 0xc5, 0xce, 0x21, 0x63, 0x87, +0xaf, 0x86, 0xcc, 0xba, 0xd6, 0xe7, 0x00, 0xf6, 0x91, 0x92, 0x92, 0xea, +0xe8, 0x42, 0x06, 0x69, 0x13, 0xf5, 0x00, 0xd0, 0xb0, 0xa7, 0xcb, 0x4c, +0xb0, 0xd2, 0x2d, 0x28, 0x63, 0xf0, 0x6a, 0xc7, 0x80, 0x6a, 0x19, 0xb2, +0x66, 0x51, 0xf3, 0xb1, 0x21, 0xa0, 0x48, 0xad, 0x1e, 0x80, 0x62, 0xaf, +0x00, 0xf4, 0xa5, 0x4e, 0x83, 0x75, 0x1b, 0xfe, 0x00, 0xc4, 0xcf, 0x55, +0xb2, 0x50, 0xa6, 0xeb, 0x38, 0xed, 0x8f, 0xd3, 0x1d, 0x00, 0xf6, 0xe3, +0x90, 0x1c, 0x60, 0x9e, 0x8e, 0xeb, 0x0b, 0xba, 0x44, 0x06, 0x68, 0xbb, +0xd3, 0x10, 0x63, 0x35, 0xe1, 0x86, 0x5c, 0x5c, 0x2b, 0x85, 0xa6, 0xe7, +0x38, 0x2c, 0x18, 0x83, 0x1f, 0x8f, 0x9b, 0x8e, 0x4d, 0x26, 0xcd, 0x34, +0x0c, 0x66, 0x1d, 0x70, 0xb7, 0x01, 0xe6, 0x02, 0xa8, 0x51, 0x63, 0xcf, +0xbb, 0x03, 0xca, 0x85, 0xc6, 0x9c, 0xf6, 0xf1, 0x51, 0xe0, 0x60, 0x07, +0x40, 0x86, 0xf0, 0x1e, 0x6e, 0xef, 0x61, 0x10, 0xd9, 0x36, 0xcc, 0xfc, +0x58, 0xe2, 0x37, 0x0d, 0x58, 0xb7, 0xbe, 0xca, 0xc9, 0xd8, 0xcd, 0xaa, +0xd5, 0x5b, 0x77, 0x83, 0xcb, 0x0e, 0x30, 0xce, 0xc8, 0xb8, 0xcd, 0xbf, +0x1e, 0x63, 0x04, 0xad, 0xb7, 0xcd, 0x43, 0x62, 0x4c, 0xe0, 0x1a, 0xd4, +0x21, 0xe2, 0xdd, 0x33, 0xdf, 0xb1, 0xdd, 0xdc, 0x01, 0x22, 0x18, 0xce, +0xa1, 0xd8, 0xcb, 0x67, 0xd5, 0x38, 0x4a, 0xbc, 0xd5, 0x81, 0x3d, 0x03, +0x98, 0x35, 0x60, 0x41, 0x85, 0x0c, 0x1d, 0xe7, 0x76, 0xf8, 0x11, 0x52, +0x76, 0xf6, 0x06, 0x16, 0x02, 0x45, 0xc8, 0xd8, 0x2f, 0x5e, 0x57, 0xbc, +0x3b, 0x89, 0x97, 0x09, 0x3e, 0x03, 0x34, 0x1a, 0x9d, 0x37, 0x87, 0x48, +0x0a, 0xe0, 0xa7, 0x4f, 0x8c, 0x3a, 0xa2, 0xaf, 0xfd, 0x7b, 0x80, 0xcf, +0xe5, 0x18, 0x61, 0x68, 0xba, 0x61, 0x8b, 0x09, 0xaa, 0xa3, 0x0c, 0x47, +0x3c, 0x43, 0x03, 0xac, 0xa3, 0x2e, 0x5e, 0x72, 0x0c, 0x80, 0x19, 0x61, +0xe6, 0x6e, 0x0e, 0xd9, 0xe8, 0xe8, 0xaf, 0x11, 0x9b, 0x4a, 0x73, 0x7a, +0x61, 0x66, 0xf0, 0x54, 0x1d, 0x18, 0xc8, 0x23, 0x36, 0xbf, 0xb5, 0xf4, +0x86, 0x54, 0xed, 0xb5, 0x91, 0xee, 0xb8, 0xbc, 0xde, 0xc3, 0x87, 0x9b, +0x2f, 0x81, 0xf2, 0xee, 0xa3, 0xec, 0x02 \ No newline at end of file diff --git a/contrib/single_file_decoder/zstd-in.c b/contrib/single_file_decoder/zstd-in.c new file mode 100644 index 00000000000..afbab99908d --- /dev/null +++ b/contrib/single_file_decoder/zstd-in.c @@ -0,0 +1,74 @@ +/** + * \file zstd.c + * Single-file Zstandard library. + * + * Generate using: + * \code + * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/compress -r ../../lib/decompress -k zstd.h -o zstd.c zstd-in.c + * \endcode + */ +/* + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +/* + * Settings to bake for the single library file. + * + * Note: It's important that none of these affects 'zstd.h' (only the + * implementation files we're amalgamating). + * + * Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also + * defined in mem.h (breaking C99 compatibility). + * + * Note: multithreading is enabled for all platforms apart from Emscripten. + */ +#define DEBUGLEVEL 0 +#define MEM_MODULE +#define XXH_NAMESPACE ZSTD_ +#define XXH_PRIVATE_API +#define XXH_INLINE_ALL +#define ZSTD_LEGACY_SUPPORT 0 +#define ZSTD_LIB_DICTBUILDER 0 +#define ZSTD_LIB_DEPRECATED 0 +#define ZSTD_NOBENCH +#ifndef __EMSCRIPTEN__ +#define ZSTD_MULTITHREAD +#endif + +/* common */ +#include "debug.c" +#include "entropy_common.c" +#include "error_private.c" +#include "fse_decompress.c" +#include "threading.c" +#include "pool.c" +#include "xxhash.c" +#include "zstd_common.c" + +/* compress */ +#include "fse_compress.c" +#include "hist.c" +#include "huf_compress.c" +#include "zstd_compress_literals.c" +#include "zstd_compress_sequences.c" +#include "zstd_compress_superblock.c" +#include "zstd_compress.c" +#include "zstd_double_fast.c" +#include "zstd_fast.c" +#include "zstd_lazy.c" +#include "zstd_ldm.c" +#include "zstd_opt.c" +#ifdef ZSTD_MULTITHREAD +#include "zstdmt_compress.c" +#endif + +/* decompress */ +#include "huf_decompress.c" +#include "zstd_ddict.c" +#include "zstd_decompress.c" +#include "zstd_decompress_block.c" diff --git a/contrib/single_file_decoder/zstd.h b/contrib/single_file_decoder/zstd.h new file mode 100644 index 00000000000..6da84e27098 --- /dev/null +++ b/contrib/single_file_decoder/zstd.h @@ -0,0 +1,2052 @@ +/* + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_H_235446 +#define ZSTD_H_235446 + +/* ====== Dependency ======*/ +#include /* INT_MAX */ +#include /* size_t */ + + +/* ===== ZSTDLIB_API : control library symbols visibility ===== */ +#ifndef ZSTDLIB_VISIBILITY +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default"))) +# else +# define ZSTDLIB_VISIBILITY +# endif +#endif +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define ZSTDLIB_API ZSTDLIB_VISIBILITY +#endif + + +/******************************************************************************* + Introduction + + zstd, short for Zstandard, is a fast lossless compression algorithm, targeting + real-time compression scenarios at zlib-level and better compression ratios. + The zstd compression library provides in-memory compression and decompression + functions. + + The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), + which is currently 22. Levels >= 20, labeled `--ultra`, should be used with + caution, as they require more memory. The library also offers negative + compression levels, which extend the range of speed vs. ratio preferences. + The lower the level, the faster the speed (at the cost of compression). + + Compression can be done in: + - a single step (described as Simple API) + - a single step, reusing a context (described as Explicit context) + - unbounded multiple steps (described as Streaming compression) + + The compression ratio achievable on small data can be highly improved using + a dictionary. Dictionary compression can be performed in: + - a single step (described as Simple dictionary API) + - a single step, reusing a dictionary (described as Bulk-processing + dictionary API) + + Advanced experimental functions can be accessed using + `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. + + Advanced experimental APIs should never be used with a dynamically-linked + library. They are not "stable"; their definitions or signatures may change in + the future. Only static linking is allowed. +*******************************************************************************/ + +/*------ Version ------*/ +#define ZSTD_VERSION_MAJOR 1 +#define ZSTD_VERSION_MINOR 4 +#define ZSTD_VERSION_RELEASE 5 + +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) +ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ + +#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE +#define ZSTD_QUOTE(str) #str +#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) +#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) +ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ + +/* ************************************* + * Default constant + ***************************************/ +#ifndef ZSTD_CLEVEL_DEFAULT +# define ZSTD_CLEVEL_DEFAULT 3 +#endif + +/* ************************************* + * Constants + ***************************************/ + +/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ +#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ +#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */ +#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 + +#define ZSTD_BLOCKSIZELOG_MAX 17 +#define ZSTD_BLOCKSIZE_MAX (1<= `ZSTD_compressBound(srcSize)`. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*! ZSTD_decompress() : + * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + * `dstCapacity` is an upper bound of originalSize to regenerate. + * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. + * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/*! ZSTD_getFrameContentSize() : requires v1.3.0+ + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + * @return : - decompressed size of `src` frame content, if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + * note 1 : a 0 return value means the frame is valid but "empty". + * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can rely on some implicit limit, + * as ZSTD_decompress() only needs an upper bound of decompressed size. + * (For example, data could be necessarily cut into blocks <= 16 KB). + * note 3 : decompressed size is always present when compression is completed using single-pass functions, + * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + * note 4 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure return value fits within application's authorized limits. + * Each application can set its own limits. + * note 6 : This function replaces ZSTD_getDecompressedSize() */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) +ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); + +/*! ZSTD_getDecompressedSize() : + * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). + * Both functions work the same way, but ZSTD_getDecompressedSize() blends + * "empty", "unknown" and "error" results to the same return value (0), + * while ZSTD_getFrameContentSize() gives them separate return values. + * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ +ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_findFrameCompressedSize() : + * `src` should point to the start of a ZSTD frame or skippable frame. + * `srcSize` must be >= first frame size + * @return : the compressed size of the first frame starting at `src`, + * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, + * or an error code if input is invalid */ +ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); + + +/*====== Helper functions ======*/ +#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ +ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ +ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ +ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ +ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ + + +/*************************************** +* Explicit context +***************************************/ +/*= Compression context + * When compressing many times, + * it is recommended to allocate a context just once, + * and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Note : re-using context is just a speed / resource optimization. + * It doesn't change the compression ratio, which remains identical. + * Note 2 : In multi-threaded environments, + * use one different context per thread for parallel execution. + */ +typedef struct ZSTD_CCtx_s ZSTD_CCtx; +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); + +/*! ZSTD_compressCCtx() : + * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. + * Important : in order to behave similarly to `ZSTD_compress()`, + * this function compresses at requested compression level, + * __ignoring any other parameter__ . + * If any advanced parameter was set using the advanced API, + * they will all be reset. Only `compressionLevel` remains. + */ +ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*= Decompression context + * When decompressing many times, + * it is recommended to allocate a context only once, + * and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Use one context per thread for parallel execution. */ +typedef struct ZSTD_DCtx_s ZSTD_DCtx; +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); + +/*! ZSTD_decompressDCtx() : + * Same as ZSTD_decompress(), + * requires an allocated ZSTD_DCtx. + * Compatible with sticky parameters. + */ +ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/*************************************** +* Advanced compression API +***************************************/ + +/* API design : + * Parameters are pushed one by one into an existing context, + * using ZSTD_CCtx_set*() functions. + * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame. + * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` ! + * __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ . + * + * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset(). + * + * This API supercedes all other "advanced" API entry points in the experimental section. + * In the future, we expect to remove from experimental API entry points which are redundant with this API. + */ + + +/* Compression strategies, listed from fastest to strongest */ +typedef enum { ZSTD_fast=1, + ZSTD_dfast=2, + ZSTD_greedy=3, + ZSTD_lazy=4, + ZSTD_lazy2=5, + ZSTD_btlazy2=6, + ZSTD_btopt=7, + ZSTD_btultra=8, + ZSTD_btultra2=9 + /* note : new strategies _might_ be added in the future. + Only the order (from fast to strong) is guaranteed */ +} ZSTD_strategy; + + +typedef enum { + + /* compression parameters + * Note: When compressing with a ZSTD_CDict these parameters are superseded + * by the parameters used to construct the ZSTD_CDict. + * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */ + ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table. + * Note that exact compression parameters are dynamically determined, + * depending on both compression level and srcSize (when known). + * Default level is ZSTD_CLEVEL_DEFAULT==3. + * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. + * Note 1 : it's possible to pass a negative compression level. + * Note 2 : setting a level does not automatically set all other compression parameters + * to default. Setting this will however eventually dynamically impact the compression + * parameters which have not been manually set. The manually set + * ones will 'stick'. */ + /* Advanced compression parameters : + * It's possible to pin down compression parameters to some specific values. + * In which case, these values are no longer dynamically selected by the compressor */ + ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2. + * This will set a memory budget for streaming decompression, + * with larger values requiring more memory + * and typically compressing more. + * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. + * Special: value 0 means "use default windowLog". + * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT + * requires explicitly allowing such size at streaming decompression stage. */ + ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. + * Resulting memory usage is (1 << (hashLog+2)). + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. + * Larger tables improve compression ratio of strategies <= dFast, + * and improve speed of strategies > dFast. + * Special: value 0 means "use default hashLog". */ + ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2. + * Resulting memory usage is (1 << (chainLog+2)). + * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. + * Larger tables result in better and slower compression. + * This parameter is useless for "fast" strategy. + * It's still useful when using "dfast" strategy, + * in which case it defines a secondary probe table. + * Special: value 0 means "use default chainLog". */ + ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2. + * More attempts result in better and slower compression. + * This parameter is useless for "fast" and "dFast" strategies. + * Special: value 0 means "use default searchLog". */ + ZSTD_c_minMatch=105, /* Minimum size of searched matches. + * Note that Zstandard can still find matches of smaller size, + * it just tweaks its search algorithm to look for this size and larger. + * Larger values increase compression and decompression speed, but decrease ratio. + * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX. + * Note that currently, for all strategies < btopt, effective minimum is 4. + * , for all strategies > fast, effective maximum is 6. + * Special: value 0 means "use default minMatchLength". */ + ZSTD_c_targetLength=106, /* Impact of this field depends on strategy. + * For strategies btopt, btultra & btultra2: + * Length of Match considered "good enough" to stop search. + * Larger values make compression stronger, and slower. + * For strategy fast: + * Distance between match sampling. + * Larger values make compression faster, and weaker. + * Special: value 0 means "use default targetLength". */ + ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition. + * The higher the value of selected strategy, the more complex it is, + * resulting in stronger and slower compression. + * Special: value 0 means "use default strategy". */ + + /* LDM mode parameters */ + ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. + * This parameter is designed to improve compression ratio + * for large inputs, by finding large matches at long distance. + * It increases memory usage and window size. + * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB + * except when expressly set to a different value. */ + ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. + * Larger values increase memory usage and compression ratio, + * but decrease compression speed. + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX + * default: windowlog - 7. + * Special: value 0 means "automatically determine hashlog". */ + ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher. + * Larger/too small values usually decrease compression ratio. + * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. + * Special: value 0 means "use default value" (default: 64). */ + ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution. + * Larger values improve collision resolution but decrease compression speed. + * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX. + * Special: value 0 means "use default value" (default: 3). */ + ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table. + * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). + * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. + * Larger values improve compression speed. + * Deviating far from default value will likely result in a compression ratio decrease. + * Special: value 0 means "automatically determine hashRateLog". */ + + /* frame parameters */ + ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) + * Content size must be known at the beginning of compression. + * This is automatically the case when using ZSTD_compress2(), + * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */ + ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */ + ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ + + /* multi-threading parameters */ + /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). + * They return an error otherwise. */ + ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. + * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() : + * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, + * while compression work is performed in parallel, within worker threads. + * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : + * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). + * More workers improve speed, but also increase memory usage. + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ + ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. + * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. + * 0 means default, which is dynamically determined based on compression parameters. + * Job size must be a minimum of overlap size, or 1 MB, whichever is largest. + * The minimum size is automatically and transparently enforced. */ + ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. + * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. + * It helps preserve compression ratio, while each job is compressed in parallel. + * This value is enforced only when nbWorkers >= 1. + * Larger values increase compression ratio, but decrease speed. + * Possible values range from 0 to 9 : + * - 0 means "default" : value will be determined by the library, depending on strategy + * - 1 means "no overlap" + * - 9 means "full overlap", using a full window size. + * Each intermediate rank increases/decreases load size by a factor 2 : + * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default + * default value varies between 6 and 9, depending on strategy */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_c_rsyncable + * ZSTD_c_format + * ZSTD_c_forceMaxWindow + * ZSTD_c_forceAttachDict + * ZSTD_c_literalCompressionMode + * ZSTD_c_targetCBlockSize + * ZSTD_c_srcSizeHint + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly; + * also, the enums values themselves are unstable and can still change. + */ + ZSTD_c_experimentalParam1=500, + ZSTD_c_experimentalParam2=10, + ZSTD_c_experimentalParam3=1000, + ZSTD_c_experimentalParam4=1001, + ZSTD_c_experimentalParam5=1002, + ZSTD_c_experimentalParam6=1003, + ZSTD_c_experimentalParam7=1004 +} ZSTD_cParameter; + +typedef struct { + size_t error; + int lowerBound; + int upperBound; +} ZSTD_bounds; + +/*! ZSTD_cParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - lower and upper bounds, both inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam); + +/*! ZSTD_CCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_cParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is generally only possible during frame initialization (before starting compression). + * Exception : when using multi-threading mode (nbWorkers >= 1), + * the following parameters can be updated _during_ compression (within same frame): + * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. + * new parameters will be active for next job only (after a flush()). + * @return : an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtx_setPledgedSrcSize() : + * Total input data size to be compressed as a single frame. + * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag. + * This value will also be controlled at end of frame, and trigger an error if not respected. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame. + * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. + * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame. + * Note 2 : pledgedSrcSize is only valid once, for the next frame. + * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN. + * Note 3 : Whenever all input data is provided and consumed in a single round, + * for example with ZSTD_compress2(), + * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), + * this value is automatically overridden by srcSize instead. + */ +ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); + +typedef enum { + ZSTD_reset_session_only = 1, + ZSTD_reset_parameters = 2, + ZSTD_reset_session_and_parameters = 3 +} ZSTD_ResetDirective; + +/*! ZSTD_CCtx_reset() : + * There are 2 different things that can be reset, independently or jointly : + * - The session : will stop compressing current frame, and make CCtx ready to start a new one. + * Useful after an error, or to interrupt any ongoing compression. + * Any internal data not yet flushed is cancelled. + * Compression parameters and dictionary remain unchanged. + * They will be used to compress next frame. + * Resetting session never fails. + * - The parameters : changes all parameters back to "default". + * This removes any reference to any dictionary too. + * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing) + * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError()) + * - Both : similar to resetting the session, followed by resetting parameters. + */ +ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); + +/*! ZSTD_compress2() : + * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API. + * ZSTD_compress2() always starts a new frame. + * Should cctx hold data from a previously unfinished frame, everything about it is forgotten. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - The function is always blocking, returns when compression is completed. + * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/*************************************** +* Advanced decompression API +***************************************/ + +/* The advanced API pushes parameters one by one into an existing DCtx context. + * Parameters are sticky, and remain valid for all following frames + * using the same DCtx context. + * It's possible to reset parameters to default values using ZSTD_DCtx_reset(). + * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream(). + * Therefore, no new decompression function is necessary. + */ + +typedef enum { + + ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which + * the streaming API will refuse to allocate memory buffer + * in order to protect the host from unreasonable memory requirements. + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT). + * Special: value 0 means "use default maximum windowLog". */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_c_format + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly + */ + ZSTD_d_experimentalParam1=1000 + +} ZSTD_dParameter; + +/*! ZSTD_dParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - both lower and upper bounds, inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam); + +/*! ZSTD_DCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_dParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is only possible during frame initialization (before starting decompression). + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value); + +/*! ZSTD_DCtx_reset() : + * Return a DCtx to clean state. + * Session and parameters can be reset jointly or separately. + * Parameters can only be reset when no active frame is being decompressed. + * @return : 0, or an error code, which can be tested with ZSTD_isError() + */ +ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); + + +/**************************** +* Streaming +****************************/ + +typedef struct ZSTD_inBuffer_s { + const void* src; /**< start of input buffer */ + size_t size; /**< size of input buffer */ + size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_inBuffer; + +typedef struct ZSTD_outBuffer_s { + void* dst; /**< start of output buffer */ + size_t size; /**< size of output buffer */ + size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_outBuffer; + + + +/*-*********************************************************************** +* Streaming compression - HowTo +* +* A ZSTD_CStream object is required to track streaming operation. +* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. +* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. +* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory. +* +* For parallel execution, use one separate ZSTD_CStream per thread. +* +* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing. +* +* Parameters are sticky : when starting a new compression on the same context, +* it will re-use the same sticky parameters as previous compression session. +* When in doubt, it's recommended to fully initialize the context before usage. +* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(), +* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to +* set more specific parameters, the pledged source size, or load a dictionary. +* +* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to +* consume input stream. The function will automatically update both `pos` +* fields within `input` and `output`. +* Note that the function may not consume the entire input, for example, because +* the output buffer is already full, in which case `input.pos < input.size`. +* The caller must check if input has been entirely consumed. +* If not, the caller must make some room to receive more compressed data, +* and then present again remaining input data. +* note: ZSTD_e_continue is guaranteed to make some forward progress when called, +* but doesn't guarantee maximal forward progress. This is especially relevant +* when compressing with multiple threads. The call won't block if it can +* consume some input, but if it can't it will wait for some, but not all, +* output to be flushed. +* @return : provides a minimum amount of data remaining to be flushed from internal buffers +* or an error code, which can be tested using ZSTD_isError(). +* +* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, +* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated. +* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0). +* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the +* operation. +* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if internal buffers are entirely flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* The epilogue is required for decoders to consider a frame completed. +* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to +* start a new frame. +* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if frame fully completed and fully flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* *******************************************************************/ + +typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ + /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ +/*===== ZSTD_CStream management functions =====*/ +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); + +/*===== Streaming compression functions =====*/ +typedef enum { + ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ + ZSTD_e_flush=1, /* flush any data provided so far, + * it creates (at least) one new block, that can be decoded immediately on reception; + * frame will continue: any future data can still reference previously compressed data, improving compression. + * note : multithreaded compression will block to flush as much output as possible. */ + ZSTD_e_end=2 /* flush any remaining data _and_ close current frame. + * note that frame is only closed after compressed data is fully flushed (return value == 0). + * After that point, any additional data starts a new frame. + * note : each frame is independent (does not reference any content from previous frame). + : note : multithreaded compression will block to flush as much output as possible. */ +} ZSTD_EndDirective; + +/*! ZSTD_compressStream2() : + * Behaves about the same as ZSTD_compressStream, with additional control on end directive. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) + * - output->pos must be <= dstCapacity, input->pos must be <= srcSize + * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. + * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available, + * and then immediately returns, just indicating that there is some data remaining to be flushed. + * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. + * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. + * - @return provides a minimum amount of data remaining to be flushed from internal buffers + * or an error code, which can be tested using ZSTD_isError(). + * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. + * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. + * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. + * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), + * only ZSTD_e_end or ZSTD_e_flush operations are allowed. + * Before starting a new compression job, or changing compression parameters, + * it is required to fully flush internal buffers. + */ +ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); + + +/* These buffer sizes are softly recommended. + * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. + * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), + * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. + * + * However, note that these recommendations are from the perspective of a C caller program. + * If the streaming interface is invoked from some other language, + * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, + * a major performance rule is to reduce crossing such interface to an absolute minimum. + * It's not rare that performance ends being spent more into the interface, rather than compression itself. + * In which cases, prefer using large buffers, as large as practical, + * for both input and output, to reduce the nb of roundtrips. + */ +ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ + + +/* ***************************************************************************** + * This following is a legacy streaming API. + * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). + * It is redundant, but remains fully supported. + * Advanced parameters and dictionary compression can only be used through the + * new API. + ******************************************************************************/ + +/*! + * Equivalent to: + * + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + */ +ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); +/*! + * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). + * NOTE: The return value is different. ZSTD_compressStream() returns a hint for + * the next read size (if non-zero and not an error). ZSTD_compressStream2() + * returns the minimum nb of bytes left to flush (if non-zero and not an error). + */ +ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ +ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ +ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); + + +/*-*************************************************************************** +* Streaming decompression - HowTo +* +* A ZSTD_DStream object is required to track streaming operations. +* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. +* ZSTD_DStream objects can be re-used multiple times. +* +* Use ZSTD_initDStream() to start a new decompression operation. +* @return : recommended first input size +* Alternatively, use advanced API to set specific properties. +* +* Use ZSTD_decompressStream() repetitively to consume your input. +* The function will update both `pos` fields. +* If `input.pos < input.size`, some input has not been consumed. +* It's up to the caller to present again remaining data. +* The function tries to flush all data decoded immediately, respecting output buffer size. +* If `output.pos < output.size`, decoder has flushed everything it could. +* But if `output.pos == output.size`, there might be some data left within internal buffers., +* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. +* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. +* @return : 0 when a frame is completely decoded and fully flushed, +* or an error code, which can be tested using ZSTD_isError(), +* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : +* the return value is a suggested next input size (just a hint for better latency) +* that will never request more than the remaining frame size. +* *******************************************************************************/ + +typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ + /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ +/*===== ZSTD_DStream management functions =====*/ +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); + +/*===== Streaming decompression functions =====*/ + +/* This function is redundant with the advanced API and equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, NULL); + */ +ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); + +ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); + +ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ + + +/************************** +* Simple dictionary API +***************************/ +/*! ZSTD_compress_usingDict() : + * Compression at an explicit compression level using a Dictionary. + * A dictionary can be any arbitrary data segment (also called a prefix), + * or a buffer with specified information (see dictBuilder/zdict.h). + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + int compressionLevel); + +/*! ZSTD_decompress_usingDict() : + * Decompression using a known Dictionary. + * Dictionary must be identical to the one used during compression. + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/*********************************** + * Bulk processing dictionary API + **********************************/ +typedef struct ZSTD_CDict_s ZSTD_CDict; + +/*! ZSTD_createCDict() : + * When compressing multiple messages or blocks using the same dictionary, + * it's recommended to digest the dictionary only once, since it's a costly operation. + * ZSTD_createCDict() will create a state from digesting a dictionary. + * The resulting state can be used for future compression operations with very limited startup cost. + * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. + * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict. + * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content. + * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer, + * in which case the only thing that it transports is the @compressionLevel. + * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, + * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, + int compressionLevel); + +/*! ZSTD_freeCDict() : + * Function frees memory allocated by ZSTD_createCDict(). */ +ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); + +/*! ZSTD_compress_usingCDict() : + * Compression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. + * Note : compression level is _decided at dictionary creation time_, + * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict); + + +typedef struct ZSTD_DDict_s ZSTD_DDict; + +/*! ZSTD_createDDict() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_freeDDict() : + * Function frees memory allocated with ZSTD_createDDict() */ +ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); + +/*! ZSTD_decompress_usingDDict() : + * Decompression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_DDict* ddict); + + +/******************************** + * Dictionary helper functions + *******************************/ + +/*! ZSTD_getDictID_fromDict() : + * Provides the dictID stored within dictionary. + * if @return == 0, the dictionary is not conformant with Zstandard specification. + * It can still be loaded, but as a content-only dictionary. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); + +/*! ZSTD_getDictID_fromDDict() : + * Provides the dictID of the dictionary loaded into `ddict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); + +/*! ZSTD_getDictID_fromFrame() : + * Provides the dictID required to decompressed the frame stored within `src`. + * If @return == 0, the dictID could not be decoded. + * This could for one of the following reasons : + * - The frame does not require a dictionary to be decoded (most common case). + * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. + * Note : this use case also happens when using a non-conformant dictionary. + * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). + * - This is not a Zstandard frame. + * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); + + +/******************************************************************************* + * Advanced dictionary and prefix API + * + * This API allows dictionaries to be used with ZSTD_compress2(), + * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and + * only reset with the context is reset with ZSTD_reset_parameters or + * ZSTD_reset_session_and_parameters. Prefixes are single-use. + ******************************************************************************/ + + +/*! ZSTD_CCtx_loadDictionary() : + * Create an internal CDict from `dict` buffer. + * Decompression will have to use same dictionary. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Dictionary is sticky, it will be used for all future compressed frames. + * To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters). + * Note 2 : Loading a dictionary involves building tables. + * It's also a CPU consuming operation, with non-negligible impact on latency. + * Tables are dependent on compression parameters, and for this reason, + * compression parameters can no longer be changed after loading a dictionary. + * Note 3 :`dict` content will be copied internally. + * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead. + * In such a case, dictionary buffer must outlive its users. + * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() + * to precisely select how dictionary content must be interpreted. */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_refCDict() : + * Reference a prepared dictionary, to be used for all next compressed frames. + * Note that compression parameters are enforced from within CDict, + * and supersede any compression parameter previously set within CCtx. + * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. + * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. + * The dictionary will remain valid for future compressed frames using same CCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Referencing a NULL CDict means "return to no-dictionary mode". + * Note 1 : Currently, only one dictionary can be managed. + * Referencing a new dictionary effectively "discards" any previous one. + * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ +ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); + +/*! ZSTD_CCtx_refPrefix() : + * Reference a prefix (single-usage dictionary) for next compressed frame. + * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). + * Decompression will need same prefix to properly regenerate data. + * Compressing with a prefix is similar in outcome as performing a diff and compressing it, + * but performs much faster, especially during decompression (compression speed is tunable with compression level). + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary + * Note 1 : Prefix buffer is referenced. It **must** outlive compression. + * Its content must remain unmodified during compression. + * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, + * ensure that the window size is large enough to contain the entire source. + * See ZSTD_c_windowLog. + * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. + * It's a CPU consuming operation, with non-negligible impact on latency. + * If there is a need to use the same prefix multiple times, consider loadDictionary instead. + * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). + * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, + const void* prefix, size_t prefixSize); + +/*! ZSTD_DCtx_loadDictionary() : + * Create an internal DDict from dict buffer, + * to be used to decompress next frames. + * The dictionary remains valid for all future frames, until explicitly invalidated. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Loading a dictionary involves building tables, + * which has a non-negligible impact on CPU usage and latency. + * It's recommended to "load once, use many times", to amortize the cost + * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading. + * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead. + * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of + * how dictionary content is loaded and interpreted. + */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_refDDict() : + * Reference a prepared dictionary, to be used to decompress next frames. + * The dictionary remains active for decompression of future frames using same DCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Currently, only one dictionary can be managed. + * Referencing a new dictionary effectively "discards" any previous one. + * Special: referencing a NULL DDict means "return to no-dictionary mode". + * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +/*! ZSTD_DCtx_refPrefix() : + * Reference a prefix (single-usage dictionary) to decompress next frame. + * This is the reverse operation of ZSTD_CCtx_refPrefix(), + * and must use the same prefix as the one used during compression. + * Prefix is **only used once**. Reference is discarded at end of frame. + * End of frame is reached when ZSTD_decompressStream() returns 0. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary + * Note 2 : Prefix buffer is referenced. It **must** outlive decompression. + * Prefix buffer must remain unmodified up to the end of frame, + * reached when ZSTD_decompressStream() returns 0. + * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent). + * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section) + * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. + * A full dictionary is more costly, as it requires building tables. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, + const void* prefix, size_t prefixSize); + +/* === Memory management === */ + +/*! ZSTD_sizeof_*() : + * These functions give the _current_ memory usage of selected object. + * Note that object memory usage can evolve (increase or decrease) over time. */ +ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); + +#endif /* ZSTD_H_235446 */ + + +/* ************************************************************************************** + * ADVANCED AND EXPERIMENTAL FUNCTIONS + **************************************************************************************** + * The definitions in the following section are considered experimental. + * They are provided for advanced scenarios. + * They should never be used with a dynamic library, as prototypes may change in the future. + * Use them only in association with static linking. + * ***************************************************************************************/ + +#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) +#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY + +/**************************************************************************************** + * experimental API (static linking only) + **************************************************************************************** + * The following symbols and constants + * are not planned to join "stable API" status in the near future. + * They can still change in future versions. + * Some of them are planned to remain in the static_only section indefinitely. + * Some of them might be removed in the future (especially when redundant with existing stable functions) + * ***************************************************************************************/ + +#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */ +#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2) +#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */ +#define ZSTD_SKIPPABLEHEADERSIZE 8 + +/* compression parameter bounds */ +#define ZSTD_WINDOWLOG_MAX_32 30 +#define ZSTD_WINDOWLOG_MAX_64 31 +#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) +#define ZSTD_WINDOWLOG_MIN 10 +#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) +#define ZSTD_HASHLOG_MIN 6 +#define ZSTD_CHAINLOG_MAX_32 29 +#define ZSTD_CHAINLOG_MAX_64 30 +#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) +#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN +#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) +#define ZSTD_SEARCHLOG_MIN 1 +#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ +#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */ +#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX +#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ +#define ZSTD_STRATEGY_MIN ZSTD_fast +#define ZSTD_STRATEGY_MAX ZSTD_btultra2 + + +#define ZSTD_OVERLAPLOG_MIN 0 +#define ZSTD_OVERLAPLOG_MAX 9 + +#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame + * requiring larger than (1< 3, then this is seqDef.offset - 3 + * If seqDef.offset < 3, then this is the corresponding repeat offset + * But if seqDef.offset < 3 and litLength == 0, this is the + * repeat offset before the corresponding repeat offset + * And if seqDef.offset == 3 and litLength == 0, this is the + * most recent repeat offset - 1 + */ + unsigned int offset; + unsigned int litLength; /* Literal length */ + unsigned int matchLength; /* Match length */ + /* 0 when seq not rep and seqDef.offset otherwise + * when litLength == 0 this will be <= 4, otherwise <= 3 like normal + */ + unsigned int rep; +} ZSTD_Sequence; + +typedef struct { + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ + unsigned hashLog; /**< dispatch table : larger == faster, more memory */ + unsigned searchLog; /**< nb of searches : larger == more compression, slower */ + unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ + unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ + ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ +} ZSTD_compressionParameters; + +typedef struct { + int contentSizeFlag; /**< 1: content size will be in frame header (when known) */ + int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */ + int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */ +} ZSTD_frameParameters; + +typedef struct { + ZSTD_compressionParameters cParams; + ZSTD_frameParameters fParams; +} ZSTD_parameters; + +typedef enum { + ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ + ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ + ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ +} ZSTD_dictContentType_e; + +typedef enum { + ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ + ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ +} ZSTD_dictLoadMethod_e; + +typedef enum { + ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ + ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. + * Useful to save 4 bytes per generated frame. + * Decoder cannot recognise automatically this format, requiring this instruction. */ +} ZSTD_format_e; + +typedef enum { + /* Note: this enum and the behavior it controls are effectively internal + * implementation details of the compressor. They are expected to continue + * to evolve and should be considered only in the context of extremely + * advanced performance tuning. + * + * Zstd currently supports the use of a CDict in three ways: + * + * - The contents of the CDict can be copied into the working context. This + * means that the compression can search both the dictionary and input + * while operating on a single set of internal tables. This makes + * the compression faster per-byte of input. However, the initial copy of + * the CDict's tables incurs a fixed cost at the beginning of the + * compression. For small compressions (< 8 KB), that copy can dominate + * the cost of the compression. + * + * - The CDict's tables can be used in-place. In this model, compression is + * slower per input byte, because the compressor has to search two sets of + * tables. However, this model incurs no start-up cost (as long as the + * working context's tables can be reused). For small inputs, this can be + * faster than copying the CDict's tables. + * + * - The CDict's tables are not used at all, and instead we use the working + * context alone to reload the dictionary and use params based on the source + * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). + * This method is effective when the dictionary sizes are very small relative + * to the input size, and the input size is fairly large to begin with. + * + * Zstd has a simple internal heuristic that selects which strategy to use + * at the beginning of a compression. However, if experimentation shows that + * Zstd is making poor choices, it is possible to override that choice with + * this enum. + */ + ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ + ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ + ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ + ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ +} ZSTD_dictAttachPref_e; + +typedef enum { + ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. + * Negative compression levels will be uncompressed, and positive compression + * levels will be compressed. */ + ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be + * emitted if Huffman compression is not profitable. */ + ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ +} ZSTD_literalCompressionMode_e; + + +/*************************************** +* Frame size functions +***************************************/ + +/*! ZSTD_findDecompressedSize() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - decompressed size of all data in all successive frames + * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * note 2 : decompressed size is always present when compression is done with ZSTD_compress() + * note 3 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure result fits within application's authorized limits. + * Each application can set its own limits. + * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + * read each contained frame header. This is fast as most of the data is skipped, + * however it does mean that all frame data must be present and valid. */ +ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_decompressBound() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - upper-bound for the decompressed size of all data in all successive frames + * - if an error occured: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. + * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. + * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value. + * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: + * upper-bound = # blocks * min(128 KB, Window_Size) + */ +ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); + +/*! ZSTD_frameHeaderSize() : + * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. + * @return : size of the Frame Header, + * or an error code (if srcSize is too small) */ +ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); + +/*! ZSTD_getSequences() : + * Extract sequences from the sequence store + * zc can be used to insert custom compression params. + * This function invokes ZSTD_compress2 + * @return : number of sequences extracted + */ +ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize); + + +/*************************************** +* Memory management +***************************************/ + +/*! ZSTD_estimate*() : + * These functions make it possible to estimate memory usage of a future + * {D,C}Ctx, before its creation. + * + * ZSTD_estimateCCtxSize() will provide a budget large enough for any + * compression level up to selected one. Unlike ZSTD_estimateCStreamSize*(), + * this estimate does not include space for a window buffer, so this estimate + * is guaranteed to be enough for single-shot compressions, but not streaming + * compressions. It will however assume the input may be arbitrarily large, + * which is the worst case. If srcSize is known to always be small, + * ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with + * ZSTD_getCParams() to create cParams from compressionLevel. + * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with + * ZSTD_CCtxParams_setParameter(). + * + * Note: only single-threaded compression is supported. This function will + * return an error code if ZSTD_c_nbWorkers is >= 1. */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); + +/*! ZSTD_estimateCStreamSize() : + * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one. + * It will also consider src size to be arbitrarily "large", which is worst case. + * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. + * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. + * Note : CStream size estimation is only correct for single-threaded compression. + * ZSTD_DStream memory budget depends on window Size. + * This information can be passed manually, using ZSTD_estimateDStreamSize, + * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); + * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + * an internal ?Dict will be created, which additional size is not estimated here. + * In this case, get total size by adding ZSTD_estimate?DictSize */ +ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize); +ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); + +/*! ZSTD_estimate?DictSize() : + * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). + * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). + * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. + */ +ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); +ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); + +/*! ZSTD_initStatic*() : + * Initialize an object using a pre-allocated fixed-size buffer. + * workspace: The memory area to emplace the object into. + * Provided pointer *must be 8-bytes aligned*. + * Buffer must outlive object. + * workspaceSize: Use ZSTD_estimate*Size() to determine + * how large workspace must be to support target scenario. + * @return : pointer to object (same address as workspace, just different type), + * or NULL if error (size too small, incorrect alignment, etc.) + * Note : zstd will never resize nor malloc() when using a static buffer. + * If the object requires more memory than available, + * zstd will just error out (typically ZSTD_error_memory_allocation). + * Note 2 : there is no corresponding "free" function. + * Since workspace is allocated externally, it must be freed externally too. + * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level + * into its associated cParams. + * Limitation 1 : currently not compatible with internal dictionary creation, triggered by + * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). + * Limitation 2 : static cctx currently not compatible with multi-threading. + * Limitation 3 : static dctx is incompatible with legacy support. + */ +ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ + +ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ + +ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams); + +ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType); + + +/*! Custom memory allocation : + * These prototypes make it possible to pass your own allocation/free functions. + * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. + * All allocation/free operations will be completed using these custom variants instead of regular ones. + */ +typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); +typedef void (*ZSTD_freeFunction) (void* opaque, void* address); +typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; +static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ + +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); + +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem); + +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem); + + + +/*************************************** +* Advanced compression functions +***************************************/ + +/*! ZSTD_createCDict_byReference() : + * Create a digested dictionary for compression + * Dictionary content is just referenced, not duplicated. + * As a consequence, `dictBuffer` **must** outlive CDict, + * and its content must remain unmodified throughout the lifetime of CDict. + * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); + +/*! ZSTD_getCParams() : + * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. + * `estimatedSrcSize` value is optional, select 0 if not known */ +ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_getParams() : + * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. + * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ +ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_checkCParams() : + * Ensure param values remain within authorized range. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */ +ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); + +/*! ZSTD_adjustCParams() : + * optimize params for a given `srcSize` and `dictSize`. + * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN. + * `dictSize` must be `0` when there is no dictionary. + * cPar can be invalid : all parameters will be clamped within valid range in the @return struct. + * This function never fails (wide contract) */ +ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); + +/*! ZSTD_compress_advanced() : + * Note : this function is now DEPRECATED. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. + * This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */ +ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + ZSTD_parameters params); + +/*! ZSTD_compress_usingCDict_advanced() : + * Note : this function is now REDUNDANT. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. + * This prototype will be marked as deprecated and generate compilation warning in some future version */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams); + + +/*! ZSTD_CCtx_loadDictionary_byReference() : + * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. + * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_loadDictionary_advanced() : + * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_CCtx_refPrefix_advanced() : + * Same as ZSTD_CCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/* === experimental parameters === */ +/* these parameters can be used with ZSTD_setParameter() + * they are not guaranteed to remain supported in the future */ + + /* Enables rsyncable mode, + * which makes compressed files more rsync friendly + * by adding periodic synchronization points to the compressed data. + * The target average block size is ZSTD_c_jobSize / 2. + * It's possible to modify the job size to increase or decrease + * the granularity of the synchronization point. + * Once the jobSize is smaller than the window size, + * it will result in compression ratio degradation. + * NOTE 1: rsyncable mode only works when multithreading is enabled. + * NOTE 2: rsyncable performs poorly in combination with long range mode, + * since it will decrease the effectiveness of synchronization points, + * though mileage may vary. + * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s. + * If the selected compression level is already running significantly slower, + * the overall speed won't be significantly impacted. + */ + #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1 + +/* Select a compression format. + * The value must be of type ZSTD_format_e. + * See ZSTD_format_e enum definition for details */ +#define ZSTD_c_format ZSTD_c_experimentalParam2 + +/* Force back-reference distances to remain < windowSize, + * even when referencing into Dictionary content (default:0) */ +#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3 + +/* Controls whether the contents of a CDict + * are used in place, or copied into the working context. + * Accepts values from the ZSTD_dictAttachPref_e enum. + * See the comments on that enum for an explanation of the feature. */ +#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 + +/* Controls how the literals are compressed (default is auto). + * The value must be of type ZSTD_literalCompressionMode_e. + * See ZSTD_literalCompressionMode_t enum definition for details. + */ +#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 + +/* Tries to fit compressed block size to be around targetCBlockSize. + * No target when targetCBlockSize == 0. + * There is no guarantee on compressed block size (default:0) */ +#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6 + +/* User's best guess of source size. + * Hint is not valid when srcSizeHint == 0. + * There is no guarantee that hint is close to actual source size, + * but compression ratio may regress significantly if guess considerably underestimates */ +#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 + +/*! ZSTD_CCtx_getParameter() : + * Get the requested compression parameter value, selected by enum ZSTD_cParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); + + +/*! ZSTD_CCtx_params : + * Quick howto : + * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure + * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into + * an existing ZSTD_CCtx_params structure. + * This is similar to + * ZSTD_CCtx_setParameter(). + * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to + * an existing CCtx. + * These parameters will be applied to + * all subsequent frames. + * - ZSTD_compressStream2() : Do compression using the CCtx. + * - ZSTD_freeCCtxParams() : Free the memory. + * + * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() + * for static allocation of CCtx for single-threaded compression. + */ +ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); +ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); + +/*! ZSTD_CCtxParams_reset() : + * Reset params to default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); + +/*! ZSTD_CCtxParams_init() : + * Initializes the compression parameters of cctxParams according to + * compression level. All other parameters are reset to their default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); + +/*! ZSTD_CCtxParams_init_advanced() : + * Initializes the compression and frame parameters of cctxParams according to + * params. All other parameters are reset to their default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); + +/*! ZSTD_CCtxParams_setParameter() : + * Similar to ZSTD_CCtx_setParameter. + * Set one compression parameter, selected by enum ZSTD_cParameter. + * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtxParams_getParameter() : + * Similar to ZSTD_CCtx_getParameter. + * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); + +/*! ZSTD_CCtx_setParametersUsingCCtxParams() : + * Apply a set of ZSTD_CCtx_params to the compression context. + * This can be done even after compression is started, + * if nbWorkers==0, this will have no impact until a new compression is started. + * if nbWorkers>=1, new parameters will be picked up at next job, + * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). + */ +ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( + ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); + +/*! ZSTD_compressStream2_simpleArgs() : + * Same as ZSTD_compressStream2(), + * but using only integral types as arguments. + * This variant might be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs ( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos, + ZSTD_EndDirective endOp); + + +/*************************************** +* Advanced decompression functions +***************************************/ + +/*! ZSTD_isFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. + * Note 3 : Skippable Frame Identifiers are considered valid. */ +ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size); + +/*! ZSTD_createDDict_byReference() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * Dictionary content is referenced, and therefore stays in dictBuffer. + * It is important that dictBuffer outlives DDict, + * it must remain read accessible throughout the lifetime of DDict */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_byReference() : + * Same as ZSTD_DCtx_loadDictionary(), + * but references `dict` content instead of copying it into `dctx`. + * This saves memory if `dict` remains around., + * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_advanced() : + * Same as ZSTD_DCtx_loadDictionary(), + * but gives direct control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_DCtx_refPrefix_advanced() : + * Same as ZSTD_DCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_DCtx_setMaxWindowSize() : + * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. + * This protects a decoder context from reserving too much memory for itself (potential attack scenario). + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); + +/* ZSTD_d_format + * experimental parameter, + * allowing selection between ZSTD_format_e input compression formats + */ +#define ZSTD_d_format ZSTD_d_experimentalParam1 + +/*! ZSTD_DCtx_setFormat() : + * Instruct the decoder context about what kind of data to decode next. + * This instruction is mandatory to decode data without a fully-formed header, + * such ZSTD_f_zstd1_magicless for example. + * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); + +/*! ZSTD_decompressStream_simpleArgs() : + * Same as ZSTD_decompressStream(), + * but using only integral types as arguments. + * This can be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( + ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos); + + +/******************************************************************** +* Advanced streaming functions +* Warning : most of these functions are now redundant with the Advanced API. +* Once Advanced API reaches "stable" status, +* redundant functions will be deprecated, and then at some point removed. +********************************************************************/ + +/*===== Advanced Streaming compression functions =====*/ +/**! ZSTD_initCStream_srcSize() : + * This function is deprecated, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * + * pledgedSrcSize must be correct. If it is not known at init time, use + * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, + * "0" also disables frame content size field. It may be enabled in the future. + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t +ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, + int compressionLevel, + unsigned long long pledgedSrcSize); + +/**! ZSTD_initCStream_usingDict() : + * This function is deprecated, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * Creates of an internal CDict (incompatible with static CCtx), except if + * dict == NULL or dictSize < 8, in which case no dict is used. + * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if + * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t +ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + int compressionLevel); + +/**! ZSTD_initCStream_advanced() : + * This function is deprecated, and is approximately equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * // Pseudocode: Set each zstd parameter and leave the rest as-is. + * for ((param, value) : params) { + * ZSTD_CCtx_setParameter(zcs, param, value); + * } + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. + * pledgedSrcSize must be correct. + * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t +ZSTD_initCStream_advanced(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + ZSTD_parameters params, + unsigned long long pledgedSrcSize); + +/**! ZSTD_initCStream_usingCDict() : + * This function is deprecated, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * note : cdict will just be referenced, and must outlive compression session + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); + +/**! ZSTD_initCStream_usingCDict_advanced() : + * This function is DEPRECATED, and is approximately equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * // Pseudocode: Set each zstd frame parameter and leave the rest as-is. + * for ((fParam, value) : fParams) { + * ZSTD_CCtx_setParameter(zcs, fParam, value); + * } + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. + * pledgedSrcSize must be correct. If srcSize is not known at init time, use + * value ZSTD_CONTENTSIZE_UNKNOWN. + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t +ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams, + unsigned long long pledgedSrcSize); + +/*! ZSTD_resetCStream() : + * This function is deprecated, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * + * start a new frame, using same parameters from previous frame. + * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. + * Note that zcs must be init at least once before using ZSTD_resetCStream(). + * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. + * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. + * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, + * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. + * @return : 0, or an error code (which can be tested using ZSTD_isError()) + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); + + +typedef struct { + unsigned long long ingested; /* nb input bytes read and buffered */ + unsigned long long consumed; /* nb input bytes actually compressed */ + unsigned long long produced; /* nb of compressed bytes generated and buffered */ + unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ + unsigned currentJobID; /* MT only : latest started job nb */ + unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ +} ZSTD_frameProgression; + +/* ZSTD_getFrameProgression() : + * tells how much data has been ingested (read from input) + * consumed (input actually compressed) and produced (output) for current frame. + * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. + * Aggregates progression inside active worker threads. + */ +ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); + +/*! ZSTD_toFlushNow() : + * Tell how many bytes are ready to be flushed immediately. + * Useful for multithreading scenarios (nbWorkers >= 1). + * Probe the oldest active job, defined as oldest job not yet entirely flushed, + * and check its output buffer. + * @return : amount of data stored in oldest job and ready to be flushed immediately. + * if @return == 0, it means either : + * + there is no active job (could be checked with ZSTD_frameProgression()), or + * + oldest job is still actively compressing data, + * but everything it has produced has also been flushed so far, + * therefore flush speed is limited by production speed of oldest job + * irrespective of the speed of concurrent (and newer) jobs. + */ +ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); + + +/*===== Advanced Streaming decompression functions =====*/ +/** + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_loadDictionary(zds, dict, dictSize); + * + * note: no dictionary will be used if dict == NULL or dictSize < 8 + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); + +/** + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, ddict); + * + * note : ddict is referenced, it must outlive decompression session + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); + +/** + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * + * re-use decompression parameters from previous init; saves dictionary loading + * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x + */ +ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); + + +/********************************************************************* +* Buffer-less and synchronous inner streaming functions +* +* This is an advanced API, giving full control over buffer management, for users which need direct control over memory. +* But it's also a complex one, with several restrictions, documented below. +* Prefer normal streaming API for an easier experience. +********************************************************************* */ + +/** + Buffer-less streaming compression (synchronous mode) + + A ZSTD_CCtx object is required to track streaming operations. + Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. + ZSTD_CCtx object can be re-used multiple times within successive compression operations. + + Start by initializing a context. + Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, + or ZSTD_compressBegin_advanced(), for finer parameter control. + It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() + + Then, consume your input using ZSTD_compressContinue(). + There are some important considerations to keep in mind when using this advanced function : + - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. + - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. + - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. + Worst case evaluation is provided by ZSTD_compressBound(). + ZSTD_compressContinue() doesn't guarantee recover after a failed compression. + - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). + It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) + - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. + In which case, it will "discard" the relevant memory section from its history. + + Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. + It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. + Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. + + `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again. +*/ + +/*===== Buffer-less streaming compression functions =====*/ +ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); +ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); +ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*- + Buffer-less streaming decompression (synchronous mode) + + A ZSTD_DCtx object is required to track streaming operations. + Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. + A ZSTD_DCtx object can be re-used multiple times. + + First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). + Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. + Data fragment must be large enough to ensure successful decoding. + `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. + @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. + >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. + errorCode, which can be tested using ZSTD_isError(). + + It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). + Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. + As a consequence, check that values remain within valid application range. + For example, do not allocate memory blindly, check that `windowSize` is within expectation. + Each application can set its own limits, depending on local restrictions. + For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. + + ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. + ZSTD_decompressContinue() is very sensitive to contiguity, + if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, + or that previous contiguous segment is large enough to properly handle maximum back-reference distance. + There are multiple ways to guarantee this condition. + + The most memory efficient way is to use a round buffer of sufficient size. + Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), + which can @return an error code if required value is too large for current system (in 32-bits mode). + In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, + up to the moment there is not enough room left in the buffer to guarantee decoding another full block, + which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. + At which point, decoding can resume from the beginning of the buffer. + Note that already decoded data stored in the buffer should be flushed before being overwritten. + + There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. + + Finally, if you control the compression process, you can also ignore all buffer size rules, + as long as the encoder and decoder progress in "lock-step", + aka use exactly the same buffer sizes, break contiguity at the same place, etc. + + Once buffers are setup, start decompression, with ZSTD_decompressBegin(). + If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). + + Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. + ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. + + @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). + It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. + It can also be an error code, which can be tested with ZSTD_isError(). + + A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. + Context can then be reset to start a new decompression. + + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + This information is not required to properly decode a frame. + + == Special case : skippable frames == + + Skippable frames allow integration of user-defined data into a flow of concatenated frames. + Skippable frames will be ignored (skipped) by decompressor. + The format of skippable frames is as follows : + a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F + b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits + c) Frame Content - any content (User Data) of length equal to Frame Size + For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. + For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. +*/ + +/*===== Buffer-less streaming decompression functions =====*/ +typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; +typedef struct { + unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ + unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ + unsigned blockSizeMax; + ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ + unsigned headerSize; + unsigned dictID; + unsigned checksumFlag; +} ZSTD_frameHeader; + +/*! ZSTD_getFrameHeader() : + * decode Frame Header, or requires larger `srcSize`. + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +/*! ZSTD_getFrameHeader_advanced() : + * same as ZSTD_getFrameHeader(), + * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ +ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); +ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* misc */ +ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + + + + +/* ============================ */ +/** Block level API */ +/* ============================ */ + +/*! + Block functions produce and decode raw zstd blocks, without frame metadata. + Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes). + But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes. + + A few rules to respect : + - Compressing and decompressing require a context structure + + Use ZSTD_createCCtx() and ZSTD_createDCtx() + - It is necessary to init context before starting + + compression : any ZSTD_compressBegin*() variant, including with dictionary + + decompression : any ZSTD_decompressBegin*() variant, including with dictionary + + copyCCtx() and copyDCtx() can be used too + - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB + + If input is larger than a block size, it's necessary to split input data into multiple blocks + + For inputs larger than a single block, consider using regular ZSTD_compress() instead. + Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block. + - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) ! + ===> In which case, nothing is produced into `dst` ! + + User __must__ test for such outcome and deal directly with uncompressed data + + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0. + Doing so would mess up with statistics history, leading to potential data corruption. + + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !! + + In case of multiple successive blocks, should some of them be uncompressed, + decoder must be informed of their existence in order to follow proper history. + Use ZSTD_insertBlock() for such a case. +*/ + +/*===== Raw zstd block functions =====*/ +ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */ + + +#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ + +#if defined (__cplusplus) +} +#endif diff --git a/contrib/single_file_decoder/zstddeclib-in.c b/contrib/single_file_decoder/zstddeclib-in.c index 5b38eae73b6..eb88af36521 100755 --- a/contrib/single_file_decoder/zstddeclib-in.c +++ b/contrib/single_file_decoder/zstddeclib-in.c @@ -7,38 +7,14 @@ * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c * \endcode */ -/* - * BSD License - * - * For Zstandard software - * - * Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. +/* + * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * All rights reserved. * - * * Neither the name Facebook nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. */ /* * Settings to bake for the standalone decompressor. @@ -60,12 +36,15 @@ #define ZSTD_NOBENCH #define ZSTD_STRIP_ERROR_STRINGS +/* common */ #include "debug.c" #include "entropy_common.c" #include "error_private.c" #include "fse_decompress.c" #include "xxhash.c" #include "zstd_common.c" + +/* decompress */ #include "huf_decompress.c" #include "zstd_ddict.c" #include "zstd_decompress.c" diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c index c8bbd778a23..8f603b02f16 100644 --- a/lib/compress/fse_compress.c +++ b/lib/compress/fse_compress.c @@ -626,7 +626,9 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize, size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e +#ifndef CHECK_F #define CHECK_F(f) { CHECK_V_F(_var_err__, f); } +#endif /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index bfc5e6efd29..ed69dfd03ca 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -41,7 +41,9 @@ #define HUF_isError ERR_isError #define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e +#ifndef CHECK_F #define CHECK_F(f) { CHECK_V_F(_var_err__, f); } +#endif /* ************************************************************** diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bb0a600729f..17b42130a95 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3749,13 +3749,16 @@ static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx) return hintInSize; } -static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, - const void* src, size_t srcSize) +#ifndef ZSTD_DECOMPRESS_INTERNAL_H /* zstd_decompress.c has the same function */ +MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { size_t const length = MIN(dstCapacity, srcSize); - if (length) memcpy(dst, src, length); + if (length > 0) { + memcpy(dst, src, length); + } return length; } +#endif /** ZSTD_compressStream_generic(): * internal function for all *compressStream*() variants diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 1770476a6d8..84703e5a49f 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1498,6 +1498,7 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) /* ***** Decompression ***** */ +#ifndef ZSTD_COMPRESS_H /* zstd_compress.c has the same function */ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { size_t const length = MIN(dstCapacity, srcSize); @@ -1506,7 +1507,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, } return length; } - +#endif size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { From 0442be5aa48022339f83e51e668fe856f1eaf64e Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Fri, 3 Apr 2020 20:34:47 +0200 Subject: [PATCH 254/402] Added missing -pthread flag (was breaking on BSD) --- contrib/single_file_decoder/build_library_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/single_file_decoder/build_library_test.sh b/contrib/single_file_decoder/build_library_test.sh index d1d5dd0eb4f..3b8b16a0580 100755 --- a/contrib/single_file_decoder/build_library_test.sh +++ b/contrib/single_file_decoder/build_library_test.sh @@ -22,7 +22,7 @@ echo "Single file library creation script: PASSED" cp "$ZSTD_SRC_ROOT/zstd.h" zstd.h # Compile the generated output -cc -Wall -Wextra -Werror -I. -Os -g0 -o $OUT_FILE zstd.c examples/roundtrip.c +cc -Wall -Wextra -Werror -pthread -I. -Os -g0 -o $OUT_FILE zstd.c examples/roundtrip.c # Did compilation work? if [ $? -ne 0 ]; then echo "Compiling roundtrip.c: FAILED" From 88da79b42e1b5ca415d85a27a5a611ee4bd61f20 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Fri, 3 Apr 2020 20:50:54 +0200 Subject: [PATCH 255/402] Minor typo --- contrib/single_file_decoder/combine.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/single_file_decoder/combine.sh b/contrib/single_file_decoder/combine.sh index ba33155fd83..ea99717f87c 100755 --- a/contrib/single_file_decoder/combine.sh +++ b/contrib/single_file_decoder/combine.sh @@ -8,7 +8,7 @@ # TODO: ROOTS, FOUND, etc., as arrays (since they fail on paths with spaces) # TODO: revert to Bash-only regex (the grep ones being too slow) # -# Author: Carl Woffenden, Numfum GmbH (this script released under a CC0 license/Public Domain) +# Author: Carl Woffenden, Numfum GmbH (this script is released under a CC0 license/Public Domain) # Common file roots ROOTS="." From bf1856c26ff9c25dd0f7d92407674593ad926e0d Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 12:07:17 -0700 Subject: [PATCH 256/402] removing max(1, ..) --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index b8194ad6132..6dd99f0fe35 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1389,7 +1389,7 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, DISPLAYLEVEL(2, "\r%79s\r", ""); DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n", srcFileName, - (double)compressedfilesize / (readsize+(!readsize)/*avoid div by zero*/) * 100, + (double)compressedfilesize / readsize * 100, (unsigned long long)readsize, (unsigned long long) compressedfilesize, dstFileName); From d0412f3abae899b368f74e98b36cd26d26d9c540 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 12:10:02 -0700 Subject: [PATCH 257/402] no percentage on readsize == 0 --- programs/fileio.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 6dd99f0fe35..f2ae1bd44bb 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -1387,11 +1387,18 @@ FIO_compressFilename_internal(FIO_prefs_t* const prefs, /* Status */ DISPLAYLEVEL(2, "\r%79s\r", ""); - DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n", - srcFileName, - (double)compressedfilesize / readsize * 100, - (unsigned long long)readsize, (unsigned long long) compressedfilesize, - dstFileName); + if (readsize == 0) { + DISPLAYLEVEL(2,"%-20s : (%6llu => %6llu bytes, %s) \n", + srcFileName, + (unsigned long long)readsize, (unsigned long long) compressedfilesize, + dstFileName); + } else { + DISPLAYLEVEL(2,"%-20s :%6.2f%% (%6llu => %6llu bytes, %s) \n", + srcFileName, + (double)compressedfilesize / readsize * 100, + (unsigned long long)readsize, (unsigned long long) compressedfilesize, + dstFileName); + } /* Elapsed Time and CPU Load */ { clock_t const cpuEnd = clock(); From 05574ec1410205e5634e5ad587ed9fcb5a4479e2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 12:40:31 -0700 Subject: [PATCH 258/402] adding oversizeDuration to dctx and macros --- lib/decompress/zstd_decompress.c | 1 + lib/decompress/zstd_decompress_internal.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 1770476a6d8..3c51db43907 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -111,6 +111,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->legacyContext = NULL; dctx->previousLegacyVersion = 0; dctx->noForwardProgress = 0; + dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); } diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 059c8194032..68c31381130 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -95,6 +95,9 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; +#define ZSTD_OVERSIZED_MAXDURATION 128 +#define ZSTD_OVERSIZED_FACTOR 3 + struct ZSTD_DCtx_s { const ZSTD_seqSymbol* LLTptr; @@ -151,6 +154,8 @@ struct ZSTD_DCtx_s /* workspace */ BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; + + size_t oversizedDuration; }; /* typedef'd to ZSTD_DCtx within "zstd.h" */ From 936aa63ff133221f7d9fb172fd198fb747a8597e Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 13:20:22 -0700 Subject: [PATCH 259/402] adding oversized check on decompression --- lib/decompress/zstd_decompress.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 3c51db43907..b37423431cf 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1508,6 +1508,24 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, return length; } +static int ZSTD_isOversized(ZSTD_DStream* zds) +{ + size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); + size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); + int const inOversized = zds->inBuffSize >= neededInBuffSize * ZSTD_OVERSIZED_FACTOR; + int const outOversized = zds->outBuffSize >= neededOutBuffSize * ZSTD_OVERSIZED_FACTOR; + return inOversized || outOversized; +} + +static void ZSTD_updateOversizedDuration(ZSTD_DStream* zds) +{ + zds->oversizedDuration += ZSTD_isOversized(zds) != 0; +} + +static int ZSTD_isOversizedTooLong(ZSTD_DStream* zds) +{ + return zds->oversizedDuration >= ZSTD_OVERSIZED_MAXDURATION; +} size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { @@ -1634,10 +1652,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize, frameParameter_windowTooLarge); + ZSTD_updateOversizedDuration(zds); /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); - if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) { + + int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); + int const tooLarge = ZSTD_isOversizedTooLong(zds); + + if (tooSmall || tooLarge) { size_t const bufferSize = neededInBuffSize + neededOutBuffSize; DEBUGLOG(4, "inBuff : from %u to %u", (U32)zds->inBuffSize, (U32)neededInBuffSize); From d598c88fb3ff590c14ce7dd62d9bbb90e672213c Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 13:31:47 -0700 Subject: [PATCH 260/402] adding fclose before return --- contrib/diagnose_corruption/check_flipped_bits.c | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c index 78473ea59f5..ed3db57de68 100644 --- a/contrib/diagnose_corruption/check_flipped_bits.c +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -105,6 +105,7 @@ static char* readFile(const char* filename, size_t* size) { bytes_read = fread(buf, 1, *size, f); if (bytes_read != *size) { fprintf(stderr, "failed to read whole file\n"); + fclose(f); free(buf); return NULL; } From 1d267dc5d661479e760b6e60bada16aa576ff944 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 13:39:02 -0700 Subject: [PATCH 261/402] returning on null check --- contrib/diagnose_corruption/check_flipped_bits.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/diagnose_corruption/check_flipped_bits.c b/contrib/diagnose_corruption/check_flipped_bits.c index ed3db57de68..cc40ab84beb 100644 --- a/contrib/diagnose_corruption/check_flipped_bits.c +++ b/contrib/diagnose_corruption/check_flipped_bits.c @@ -100,6 +100,8 @@ static char* readFile(const char* filename, size_t* size) { buf = malloc(*size); if (buf == NULL) { fprintf(stderr, "malloc failed\n"); + fclose(f); + return NULL; } bytes_read = fread(buf, 1, *size, f); From a4cbe79ccb84092777b0f5d7c69f30d47b832d54 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 14:09:21 -0700 Subject: [PATCH 262/402] Using in and out size together --- lib/decompress/zstd_decompress.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index b37423431cf..2c87a41d514 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1512,9 +1512,7 @@ static int ZSTD_isOversized(ZSTD_DStream* zds) { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); - int const inOversized = zds->inBuffSize >= neededInBuffSize * ZSTD_OVERSIZED_FACTOR; - int const outOversized = zds->outBuffSize >= neededOutBuffSize * ZSTD_OVERSIZED_FACTOR; - return inOversized || outOversized; + return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_OVERSIZED_FACTOR; } static void ZSTD_updateOversizedDuration(ZSTD_DStream* zds) From ae47d503559659ef6e0878d30fdc7a6ed584ed49 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 14:12:23 -0700 Subject: [PATCH 263/402] only computing sizes once --- lib/decompress/zstd_decompress.c | 63 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 2c87a41d514..ba64689f0a6 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1508,16 +1508,14 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, return length; } -static int ZSTD_isOversized(ZSTD_DStream* zds) +static int ZSTD_isOversized(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { - size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); - size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_OVERSIZED_FACTOR; } -static void ZSTD_updateOversizedDuration(ZSTD_DStream* zds) +static void ZSTD_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { - zds->oversizedDuration += ZSTD_isOversized(zds) != 0; + zds->oversizedDuration += ZSTD_isOversized(zds, neededInBuffSize, neededOutBuffSize) != 0; } static int ZSTD_isOversizedTooLong(ZSTD_DStream* zds) @@ -1650,37 +1648,38 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize, frameParameter_windowTooLarge); - ZSTD_updateOversizedDuration(zds); /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); - int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); - int const tooLarge = ZSTD_isOversizedTooLong(zds); - - if (tooSmall || tooLarge) { - size_t const bufferSize = neededInBuffSize + neededOutBuffSize; - DEBUGLOG(4, "inBuff : from %u to %u", - (U32)zds->inBuffSize, (U32)neededInBuffSize); - DEBUGLOG(4, "outBuff : from %u to %u", - (U32)zds->outBuffSize, (U32)neededOutBuffSize); - if (zds->staticSize) { /* static DCtx */ - DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize); - assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ - RETURN_ERROR_IF( - bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), - memory_allocation); - } else { - ZSTD_free(zds->inBuff, zds->customMem); - zds->inBuffSize = 0; - zds->outBuffSize = 0; - zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); - RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation); - } - zds->inBuffSize = neededInBuffSize; - zds->outBuff = zds->inBuff + zds->inBuffSize; - zds->outBuffSize = neededOutBuffSize; - } } + ZSTD_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize); + + { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); + int const tooLarge = ZSTD_isOversizedTooLong(zds); + + if (tooSmall || tooLarge) { + size_t const bufferSize = neededInBuffSize + neededOutBuffSize; + DEBUGLOG(4, "inBuff : from %u to %u", + (U32)zds->inBuffSize, (U32)neededInBuffSize); + DEBUGLOG(4, "outBuff : from %u to %u", + (U32)zds->outBuffSize, (U32)neededOutBuffSize); + if (zds->staticSize) { /* static DCtx */ + DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize); + assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ + RETURN_ERROR_IF( + bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), + memory_allocation); + } else { + ZSTD_free(zds->inBuff, zds->customMem); + zds->inBuffSize = 0; + zds->outBuffSize = 0; + zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); + RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation); + } + zds->inBuffSize = neededInBuffSize; + zds->outBuff = zds->inBuff + zds->inBuffSize; + zds->outBuffSize = neededOutBuffSize; + } } } zds->streamStage = zdss_read; /* fall-through */ From 3a4c8cc9b37964b8f1e7975a85ac94d1f2843bb0 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 14:14:46 -0700 Subject: [PATCH 264/402] adding dctx to function name --- lib/decompress/zstd_decompress.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index ba64689f0a6..7ab2baf3163 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1508,17 +1508,17 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, return length; } -static int ZSTD_isOversized(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) +static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_OVERSIZED_FACTOR; } -static void ZSTD_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) +static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { - zds->oversizedDuration += ZSTD_isOversized(zds, neededInBuffSize, neededOutBuffSize) != 0; + zds->oversizedDuration += ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize) != 0; } -static int ZSTD_isOversizedTooLong(ZSTD_DStream* zds) +static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds) { return zds->oversizedDuration >= ZSTD_OVERSIZED_MAXDURATION; } @@ -1652,10 +1652,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); - ZSTD_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize); + ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize); { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); - int const tooLarge = ZSTD_isOversizedTooLong(zds); + int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds); if (tooSmall || tooLarge) { size_t const bufferSize = neededInBuffSize + neededOutBuffSize; From 0a172c5e437237a197c13646839ac9ef6e101548 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 14:21:24 -0700 Subject: [PATCH 265/402] converting to if --- lib/decompress/zstd_decompress.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 7ab2baf3163..c3690f022a1 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1515,7 +1515,10 @@ static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { - zds->oversizedDuration += ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize) != 0; + if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize)) + zds->oversizedDuration++; + else + zds->oversizedDuration = 0; } static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds) From 01548667491ff72d264b265f5ab8d3673487b9cf Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 3 Apr 2020 14:26:15 -0700 Subject: [PATCH 266/402] moving consts to zstd_internal and reusing them --- lib/common/zstd_internal.h | 10 ++++++++++ lib/compress/zstd_cwksp.h | 10 ---------- lib/decompress/zstd_decompress.c | 4 ++-- lib/decompress/zstd_decompress_internal.h | 3 --- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index ce80f8c5639..099a98e7744 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -248,6 +248,16 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e } } +/* define "workspace is too large" as this number of times larger than needed */ +#define ZSTD_WORKSPACETOOLARGE_FACTOR 3 + +/* when workspace is continuously too large + * during at least this number of times, + * context's memory usage is considered wasteful, + * because it's sized to handle a worst case scenario which rarely happens. + * In which case, resize it down to free some memory */ +#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 + /*-******************************************* * Private declarations diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 2dfab3a4e3e..5886893d711 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -24,16 +24,6 @@ extern "C" { * Constants ***************************************/ -/* define "workspace is too large" as this number of times larger than needed */ -#define ZSTD_WORKSPACETOOLARGE_FACTOR 3 - -/* when workspace is continuously too large - * during at least this number of times, - * context's memory usage is considered wasteful, - * because it's sized to handle a worst case scenario which rarely happens. - * In which case, resize it down to free some memory */ -#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 - /* Since the workspace is effectively its own little malloc implementation / * arena, when we run under ASAN, we should similarly insert redzones between * each internal element of the workspace, so ASAN will catch overruns that diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index c3690f022a1..7547230428c 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1510,7 +1510,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { - return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_OVERSIZED_FACTOR; + return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR; } static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) @@ -1523,7 +1523,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds) { - return zds->oversizedDuration >= ZSTD_OVERSIZED_MAXDURATION; + return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION; } size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 68c31381130..29b4d0acc21 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -95,9 +95,6 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; -#define ZSTD_OVERSIZED_MAXDURATION 128 -#define ZSTD_OVERSIZED_FACTOR 3 - struct ZSTD_DCtx_s { const ZSTD_seqSymbol* LLTptr; From 31e76f1ed4f1fd34b2e1b0cfd78ea2f4e2930306 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Sat, 4 Apr 2020 08:49:24 -0700 Subject: [PATCH 267/402] adding test for dctx size reduction --- tests/fuzzer.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 1333ec9b43c..c102046c30f 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -525,7 +525,48 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++) + DISPLAYLEVEL(3, "test%3d: check DCtx size is reduced after many oversized calls : ", testNb++); + { + size_t const largeFrameSrcSize = 200; + size_t const smallFrameSrcSize = 10; + size_t const nbFrames = 256; + + size_t i = 0, consumed = 0, produced = 0, prevDCtxSize = 0; + int sizeReduced = 0; + + BYTE* const dst = (BYTE*)compressedBuffer; + ZSTD_DCtx* dctx = ZSTD_createDCtx(); + + /* create a large frame and then a bunch of small frames */ + size_t srcSize = ZSTD_compress((void*)dst, + compressedBufferSize, CNBuffer, largeFrameSrcSize, 3); + for (i = 0; i < nbFrames; i++) + srcSize += ZSTD_compress((void*)(dst + srcSize), + compressedBufferSize - srcSize, CNBuffer, + smallFrameSrcSize, 3); + + /* decompressStream and make sure that dctx size was reduced at least once */ + while (consumed < srcSize) { + ZSTD_inBuffer in = {(void*)(dst + consumed), MIN(1, srcSize - consumed), 0}; + ZSTD_outBuffer out = {(BYTE*)CNBuffer + produced, CNBuffSize - produced, 0}; + ZSTD_decompressStream(dctx, &out, &in); + consumed += in.pos; + produced += out.pos; + + /* success! size was reduced from the previous frame */ + if (prevDCtxSize > ZSTD_sizeof_DCtx(dctx)) + sizeReduced = 1; + + prevDCtxSize = ZSTD_sizeof_DCtx(dctx); + } + + assert(sizeReduced); + + ZSTD_freeDCtx(dctx); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); const BYTE* src = (BYTE*)CNBuffer; BYTE* dst = (BYTE*)compressedBuffer; From 794f03459e0d511b3e72185a24bbff5992f768c1 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 6 Apr 2020 22:57:49 -0700 Subject: [PATCH 268/402] adding refPrefix --- tests/fuzz/dictionary_round_trip.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/fuzz/dictionary_round_trip.c b/tests/fuzz/dictionary_round_trip.c index a0e7037c0ea..ce3cd672797 100644 --- a/tests/fuzz/dictionary_round_trip.c +++ b/tests/fuzz/dictionary_round_trip.c @@ -32,6 +32,7 @@ static size_t roundTripTest(void *result, size_t resultCapacity, { ZSTD_dictContentType_e dictContentType = ZSTD_dct_auto; FUZZ_dict_t dict = FUZZ_train(src, srcSize, producer); + int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0; size_t cSize; if (FUZZ_dataProducer_uint32Range(producer, 0, 15) == 0) { int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel); @@ -46,17 +47,27 @@ static size_t roundTripTest(void *result, size_t resultCapacity, FUZZ_setRandomParameters(cctx, srcSize, producer); /* Disable checksum so we can use sizes smaller than compress bound. */ FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0)); - FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( + if (refPrefix) + FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced( + cctx, dict.buff, dict.size, + dictContentType)); + else + FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( cctx, dict.buff, dict.size, (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), dictContentType)); cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize); } FUZZ_ZASSERT(cSize); - FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( - dctx, dict.buff, dict.size, - (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), - dictContentType)); + if (refPrefix) + FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced( + dctx, dict.buff, dict.size, + dictContentType)); + else + FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( + dctx, dict.buff, dict.size, + (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), + dictContentType)); { size_t const ret = ZSTD_decompressDCtx( dctx, result, resultCapacity, compressed, cSize); From edd9a07322eeddc888cf1875dc6b6f2499be5f46 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 11:02:06 +0200 Subject: [PATCH 269/402] Code replicated in compression and decompression moved to shared headers `CHECK_F` macro moved to `error_private.h` (shared between `fse_compress.c` and `fse_decompress.c`). `ZSTD_limitCopy()` moved to `zstd_internal.h` (shared between `zstd_compress.c` and `zstd_decompress.c`). Erroneous build artefact `zstd.h` removed from repo. --- contrib/single_file_decoder/.gitignore | 2 +- contrib/single_file_decoder/zstd.h | 2052 ------------------------ lib/common/error_private.h | 4 + lib/common/fse_decompress.c | 5 - lib/common/zstd_internal.h | 8 + lib/compress/fse_compress.c | 5 - lib/compress/zstd_compress.c | 11 - lib/decompress/zstd_decompress.c | 11 - 8 files changed, 13 insertions(+), 2085 deletions(-) delete mode 100644 contrib/single_file_decoder/zstd.h diff --git a/contrib/single_file_decoder/.gitignore b/contrib/single_file_decoder/.gitignore index 7084123b5e1..054333f9b98 100644 --- a/contrib/single_file_decoder/.gitignore +++ b/contrib/single_file_decoder/.gitignore @@ -1,4 +1,4 @@ zstddeclib.c zstdenclib.c zstd.c -zsdt.h +zstd.h diff --git a/contrib/single_file_decoder/zstd.h b/contrib/single_file_decoder/zstd.h deleted file mode 100644 index 6da84e27098..00000000000 --- a/contrib/single_file_decoder/zstd.h +++ /dev/null @@ -1,2052 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ -#if defined (__cplusplus) -extern "C" { -#endif - -#ifndef ZSTD_H_235446 -#define ZSTD_H_235446 - -/* ====== Dependency ======*/ -#include /* INT_MAX */ -#include /* size_t */ - - -/* ===== ZSTDLIB_API : control library symbols visibility ===== */ -#ifndef ZSTDLIB_VISIBILITY -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default"))) -# else -# define ZSTDLIB_VISIBILITY -# endif -#endif -#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) -# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY -#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) -# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ -#else -# define ZSTDLIB_API ZSTDLIB_VISIBILITY -#endif - - -/******************************************************************************* - Introduction - - zstd, short for Zstandard, is a fast lossless compression algorithm, targeting - real-time compression scenarios at zlib-level and better compression ratios. - The zstd compression library provides in-memory compression and decompression - functions. - - The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), - which is currently 22. Levels >= 20, labeled `--ultra`, should be used with - caution, as they require more memory. The library also offers negative - compression levels, which extend the range of speed vs. ratio preferences. - The lower the level, the faster the speed (at the cost of compression). - - Compression can be done in: - - a single step (described as Simple API) - - a single step, reusing a context (described as Explicit context) - - unbounded multiple steps (described as Streaming compression) - - The compression ratio achievable on small data can be highly improved using - a dictionary. Dictionary compression can be performed in: - - a single step (described as Simple dictionary API) - - a single step, reusing a dictionary (described as Bulk-processing - dictionary API) - - Advanced experimental functions can be accessed using - `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. - - Advanced experimental APIs should never be used with a dynamically-linked - library. They are not "stable"; their definitions or signatures may change in - the future. Only static linking is allowed. -*******************************************************************************/ - -/*------ Version ------*/ -#define ZSTD_VERSION_MAJOR 1 -#define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 5 - -#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) -ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ - -#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE -#define ZSTD_QUOTE(str) #str -#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) -#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) -ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ - -/* ************************************* - * Default constant - ***************************************/ -#ifndef ZSTD_CLEVEL_DEFAULT -# define ZSTD_CLEVEL_DEFAULT 3 -#endif - -/* ************************************* - * Constants - ***************************************/ - -/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ -#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ -#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ -#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */ -#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 - -#define ZSTD_BLOCKSIZELOG_MAX 17 -#define ZSTD_BLOCKSIZE_MAX (1<= `ZSTD_compressBound(srcSize)`. - * @return : compressed size written into `dst` (<= `dstCapacity), - * or an error code if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - -/*! ZSTD_decompress() : - * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - * `dstCapacity` is an upper bound of originalSize to regenerate. - * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. - * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), - * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, - const void* src, size_t compressedSize); - -/*! ZSTD_getFrameContentSize() : requires v1.3.0+ - * `src` should point to the start of a ZSTD encoded frame. - * `srcSize` must be at least as large as the frame header. - * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. - * @return : - decompressed size of `src` frame content, if known - * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) - * note 1 : a 0 return value means the frame is valid but "empty". - * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * Optionally, application can rely on some implicit limit, - * as ZSTD_decompress() only needs an upper bound of decompressed size. - * (For example, data could be necessarily cut into blocks <= 16 KB). - * note 3 : decompressed size is always present when compression is completed using single-pass functions, - * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). - * note 4 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure return value fits within application's authorized limits. - * Each application can set its own limits. - * note 6 : This function replaces ZSTD_getDecompressedSize() */ -#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) -#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) -ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); - -/*! ZSTD_getDecompressedSize() : - * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). - * Both functions work the same way, but ZSTD_getDecompressedSize() blends - * "empty", "unknown" and "error" results to the same return value (0), - * while ZSTD_getFrameContentSize() gives them separate return values. - * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ -ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); - -/*! ZSTD_findFrameCompressedSize() : - * `src` should point to the start of a ZSTD frame or skippable frame. - * `srcSize` must be >= first frame size - * @return : the compressed size of the first frame starting at `src`, - * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, - * or an error code if input is invalid */ -ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); - - -/*====== Helper functions ======*/ -#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ -ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ -ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ -ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ -ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ -ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ - - -/*************************************** -* Explicit context -***************************************/ -/*= Compression context - * When compressing many times, - * it is recommended to allocate a context just once, - * and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Note : re-using context is just a speed / resource optimization. - * It doesn't change the compression ratio, which remains identical. - * Note 2 : In multi-threaded environments, - * use one different context per thread for parallel execution. - */ -typedef struct ZSTD_CCtx_s ZSTD_CCtx; -ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); -ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); - -/*! ZSTD_compressCCtx() : - * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. - * Important : in order to behave similarly to `ZSTD_compress()`, - * this function compresses at requested compression level, - * __ignoring any other parameter__ . - * If any advanced parameter was set using the advanced API, - * they will all be reset. Only `compressionLevel` remains. - */ -ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - -/*= Decompression context - * When decompressing many times, - * it is recommended to allocate a context only once, - * and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Use one context per thread for parallel execution. */ -typedef struct ZSTD_DCtx_s ZSTD_DCtx; -ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); -ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); - -/*! ZSTD_decompressDCtx() : - * Same as ZSTD_decompress(), - * requires an allocated ZSTD_DCtx. - * Compatible with sticky parameters. - */ -ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - - -/*************************************** -* Advanced compression API -***************************************/ - -/* API design : - * Parameters are pushed one by one into an existing context, - * using ZSTD_CCtx_set*() functions. - * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame. - * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` ! - * __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ . - * - * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset(). - * - * This API supercedes all other "advanced" API entry points in the experimental section. - * In the future, we expect to remove from experimental API entry points which are redundant with this API. - */ - - -/* Compression strategies, listed from fastest to strongest */ -typedef enum { ZSTD_fast=1, - ZSTD_dfast=2, - ZSTD_greedy=3, - ZSTD_lazy=4, - ZSTD_lazy2=5, - ZSTD_btlazy2=6, - ZSTD_btopt=7, - ZSTD_btultra=8, - ZSTD_btultra2=9 - /* note : new strategies _might_ be added in the future. - Only the order (from fast to strong) is guaranteed */ -} ZSTD_strategy; - - -typedef enum { - - /* compression parameters - * Note: When compressing with a ZSTD_CDict these parameters are superseded - * by the parameters used to construct the ZSTD_CDict. - * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */ - ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table. - * Note that exact compression parameters are dynamically determined, - * depending on both compression level and srcSize (when known). - * Default level is ZSTD_CLEVEL_DEFAULT==3. - * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. - * Note 1 : it's possible to pass a negative compression level. - * Note 2 : setting a level does not automatically set all other compression parameters - * to default. Setting this will however eventually dynamically impact the compression - * parameters which have not been manually set. The manually set - * ones will 'stick'. */ - /* Advanced compression parameters : - * It's possible to pin down compression parameters to some specific values. - * In which case, these values are no longer dynamically selected by the compressor */ - ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2. - * This will set a memory budget for streaming decompression, - * with larger values requiring more memory - * and typically compressing more. - * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. - * Special: value 0 means "use default windowLog". - * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT - * requires explicitly allowing such size at streaming decompression stage. */ - ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. - * Resulting memory usage is (1 << (hashLog+2)). - * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. - * Larger tables improve compression ratio of strategies <= dFast, - * and improve speed of strategies > dFast. - * Special: value 0 means "use default hashLog". */ - ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2. - * Resulting memory usage is (1 << (chainLog+2)). - * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. - * Larger tables result in better and slower compression. - * This parameter is useless for "fast" strategy. - * It's still useful when using "dfast" strategy, - * in which case it defines a secondary probe table. - * Special: value 0 means "use default chainLog". */ - ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2. - * More attempts result in better and slower compression. - * This parameter is useless for "fast" and "dFast" strategies. - * Special: value 0 means "use default searchLog". */ - ZSTD_c_minMatch=105, /* Minimum size of searched matches. - * Note that Zstandard can still find matches of smaller size, - * it just tweaks its search algorithm to look for this size and larger. - * Larger values increase compression and decompression speed, but decrease ratio. - * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX. - * Note that currently, for all strategies < btopt, effective minimum is 4. - * , for all strategies > fast, effective maximum is 6. - * Special: value 0 means "use default minMatchLength". */ - ZSTD_c_targetLength=106, /* Impact of this field depends on strategy. - * For strategies btopt, btultra & btultra2: - * Length of Match considered "good enough" to stop search. - * Larger values make compression stronger, and slower. - * For strategy fast: - * Distance between match sampling. - * Larger values make compression faster, and weaker. - * Special: value 0 means "use default targetLength". */ - ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition. - * The higher the value of selected strategy, the more complex it is, - * resulting in stronger and slower compression. - * Special: value 0 means "use default strategy". */ - - /* LDM mode parameters */ - ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. - * This parameter is designed to improve compression ratio - * for large inputs, by finding large matches at long distance. - * It increases memory usage and window size. - * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB - * except when expressly set to a different value. */ - ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. - * Larger values increase memory usage and compression ratio, - * but decrease compression speed. - * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX - * default: windowlog - 7. - * Special: value 0 means "automatically determine hashlog". */ - ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher. - * Larger/too small values usually decrease compression ratio. - * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. - * Special: value 0 means "use default value" (default: 64). */ - ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution. - * Larger values improve collision resolution but decrease compression speed. - * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX. - * Special: value 0 means "use default value" (default: 3). */ - ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table. - * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). - * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. - * Larger values improve compression speed. - * Deviating far from default value will likely result in a compression ratio decrease. - * Special: value 0 means "automatically determine hashRateLog". */ - - /* frame parameters */ - ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) - * Content size must be known at the beginning of compression. - * This is automatically the case when using ZSTD_compress2(), - * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */ - ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */ - ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ - - /* multi-threading parameters */ - /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). - * They return an error otherwise. */ - ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. - * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() : - * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, - * while compression work is performed in parallel, within worker threads. - * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : - * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). - * More workers improve speed, but also increase memory usage. - * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ - ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. - * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. - * 0 means default, which is dynamically determined based on compression parameters. - * Job size must be a minimum of overlap size, or 1 MB, whichever is largest. - * The minimum size is automatically and transparently enforced. */ - ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. - * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. - * It helps preserve compression ratio, while each job is compressed in parallel. - * This value is enforced only when nbWorkers >= 1. - * Larger values increase compression ratio, but decrease speed. - * Possible values range from 0 to 9 : - * - 0 means "default" : value will be determined by the library, depending on strategy - * - 1 means "no overlap" - * - 9 means "full overlap", using a full window size. - * Each intermediate rank increases/decreases load size by a factor 2 : - * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default - * default value varies between 6 and 9, depending on strategy */ - - /* note : additional experimental parameters are also available - * within the experimental section of the API. - * At the time of this writing, they include : - * ZSTD_c_rsyncable - * ZSTD_c_format - * ZSTD_c_forceMaxWindow - * ZSTD_c_forceAttachDict - * ZSTD_c_literalCompressionMode - * ZSTD_c_targetCBlockSize - * ZSTD_c_srcSizeHint - * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. - * note : never ever use experimentalParam? names directly; - * also, the enums values themselves are unstable and can still change. - */ - ZSTD_c_experimentalParam1=500, - ZSTD_c_experimentalParam2=10, - ZSTD_c_experimentalParam3=1000, - ZSTD_c_experimentalParam4=1001, - ZSTD_c_experimentalParam5=1002, - ZSTD_c_experimentalParam6=1003, - ZSTD_c_experimentalParam7=1004 -} ZSTD_cParameter; - -typedef struct { - size_t error; - int lowerBound; - int upperBound; -} ZSTD_bounds; - -/*! ZSTD_cParam_getBounds() : - * All parameters must belong to an interval with lower and upper bounds, - * otherwise they will either trigger an error or be automatically clamped. - * @return : a structure, ZSTD_bounds, which contains - * - an error status field, which must be tested using ZSTD_isError() - * - lower and upper bounds, both inclusive - */ -ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam); - -/*! ZSTD_CCtx_setParameter() : - * Set one compression parameter, selected by enum ZSTD_cParameter. - * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds(). - * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). - * Setting a parameter is generally only possible during frame initialization (before starting compression). - * Exception : when using multi-threading mode (nbWorkers >= 1), - * the following parameters can be updated _during_ compression (within same frame): - * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. - * new parameters will be active for next job only (after a flush()). - * @return : an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value); - -/*! ZSTD_CCtx_setPledgedSrcSize() : - * Total input data size to be compressed as a single frame. - * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag. - * This value will also be controlled at end of frame, and trigger an error if not respected. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame. - * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. - * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame. - * Note 2 : pledgedSrcSize is only valid once, for the next frame. - * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN. - * Note 3 : Whenever all input data is provided and consumed in a single round, - * for example with ZSTD_compress2(), - * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), - * this value is automatically overridden by srcSize instead. - */ -ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); - -typedef enum { - ZSTD_reset_session_only = 1, - ZSTD_reset_parameters = 2, - ZSTD_reset_session_and_parameters = 3 -} ZSTD_ResetDirective; - -/*! ZSTD_CCtx_reset() : - * There are 2 different things that can be reset, independently or jointly : - * - The session : will stop compressing current frame, and make CCtx ready to start a new one. - * Useful after an error, or to interrupt any ongoing compression. - * Any internal data not yet flushed is cancelled. - * Compression parameters and dictionary remain unchanged. - * They will be used to compress next frame. - * Resetting session never fails. - * - The parameters : changes all parameters back to "default". - * This removes any reference to any dictionary too. - * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing) - * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError()) - * - Both : similar to resetting the session, followed by resetting parameters. - */ -ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); - -/*! ZSTD_compress2() : - * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API. - * ZSTD_compress2() always starts a new frame. - * Should cctx hold data from a previously unfinished frame, everything about it is forgotten. - * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() - * - The function is always blocking, returns when compression is completed. - * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. - * @return : compressed size written into `dst` (<= `dstCapacity), - * or an error code if it fails (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - - -/*************************************** -* Advanced decompression API -***************************************/ - -/* The advanced API pushes parameters one by one into an existing DCtx context. - * Parameters are sticky, and remain valid for all following frames - * using the same DCtx context. - * It's possible to reset parameters to default values using ZSTD_DCtx_reset(). - * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream(). - * Therefore, no new decompression function is necessary. - */ - -typedef enum { - - ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which - * the streaming API will refuse to allocate memory buffer - * in order to protect the host from unreasonable memory requirements. - * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. - * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT). - * Special: value 0 means "use default maximum windowLog". */ - - /* note : additional experimental parameters are also available - * within the experimental section of the API. - * At the time of this writing, they include : - * ZSTD_c_format - * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. - * note : never ever use experimentalParam? names directly - */ - ZSTD_d_experimentalParam1=1000 - -} ZSTD_dParameter; - -/*! ZSTD_dParam_getBounds() : - * All parameters must belong to an interval with lower and upper bounds, - * otherwise they will either trigger an error or be automatically clamped. - * @return : a structure, ZSTD_bounds, which contains - * - an error status field, which must be tested using ZSTD_isError() - * - both lower and upper bounds, inclusive - */ -ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam); - -/*! ZSTD_DCtx_setParameter() : - * Set one compression parameter, selected by enum ZSTD_dParameter. - * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds(). - * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). - * Setting a parameter is only possible during frame initialization (before starting decompression). - * @return : 0, or an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value); - -/*! ZSTD_DCtx_reset() : - * Return a DCtx to clean state. - * Session and parameters can be reset jointly or separately. - * Parameters can only be reset when no active frame is being decompressed. - * @return : 0, or an error code, which can be tested with ZSTD_isError() - */ -ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); - - -/**************************** -* Streaming -****************************/ - -typedef struct ZSTD_inBuffer_s { - const void* src; /**< start of input buffer */ - size_t size; /**< size of input buffer */ - size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ -} ZSTD_inBuffer; - -typedef struct ZSTD_outBuffer_s { - void* dst; /**< start of output buffer */ - size_t size; /**< size of output buffer */ - size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ -} ZSTD_outBuffer; - - - -/*-*********************************************************************** -* Streaming compression - HowTo -* -* A ZSTD_CStream object is required to track streaming operation. -* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. -* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. -* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory. -* -* For parallel execution, use one separate ZSTD_CStream per thread. -* -* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing. -* -* Parameters are sticky : when starting a new compression on the same context, -* it will re-use the same sticky parameters as previous compression session. -* When in doubt, it's recommended to fully initialize the context before usage. -* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(), -* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to -* set more specific parameters, the pledged source size, or load a dictionary. -* -* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to -* consume input stream. The function will automatically update both `pos` -* fields within `input` and `output`. -* Note that the function may not consume the entire input, for example, because -* the output buffer is already full, in which case `input.pos < input.size`. -* The caller must check if input has been entirely consumed. -* If not, the caller must make some room to receive more compressed data, -* and then present again remaining input data. -* note: ZSTD_e_continue is guaranteed to make some forward progress when called, -* but doesn't guarantee maximal forward progress. This is especially relevant -* when compressing with multiple threads. The call won't block if it can -* consume some input, but if it can't it will wait for some, but not all, -* output to be flushed. -* @return : provides a minimum amount of data remaining to be flushed from internal buffers -* or an error code, which can be tested using ZSTD_isError(). -* -* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, -* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated. -* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0). -* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush. -* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the -* operation. -* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will -* block until the flush is complete or the output buffer is full. -* @return : 0 if internal buffers are entirely flushed, -* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), -* or an error code, which can be tested using ZSTD_isError(). -* -* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame. -* It will perform a flush and write frame epilogue. -* The epilogue is required for decoders to consider a frame completed. -* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush. -* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to -* start a new frame. -* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will -* block until the flush is complete or the output buffer is full. -* @return : 0 if frame fully completed and fully flushed, -* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), -* or an error code, which can be tested using ZSTD_isError(). -* -* *******************************************************************/ - -typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ - /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ -/*===== ZSTD_CStream management functions =====*/ -ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); -ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); - -/*===== Streaming compression functions =====*/ -typedef enum { - ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ - ZSTD_e_flush=1, /* flush any data provided so far, - * it creates (at least) one new block, that can be decoded immediately on reception; - * frame will continue: any future data can still reference previously compressed data, improving compression. - * note : multithreaded compression will block to flush as much output as possible. */ - ZSTD_e_end=2 /* flush any remaining data _and_ close current frame. - * note that frame is only closed after compressed data is fully flushed (return value == 0). - * After that point, any additional data starts a new frame. - * note : each frame is independent (does not reference any content from previous frame). - : note : multithreaded compression will block to flush as much output as possible. */ -} ZSTD_EndDirective; - -/*! ZSTD_compressStream2() : - * Behaves about the same as ZSTD_compressStream, with additional control on end directive. - * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() - * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) - * - output->pos must be <= dstCapacity, input->pos must be <= srcSize - * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. - * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. - * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available, - * and then immediately returns, just indicating that there is some data remaining to be flushed. - * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. - * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. - * - @return provides a minimum amount of data remaining to be flushed from internal buffers - * or an error code, which can be tested using ZSTD_isError(). - * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. - * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. - * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. - * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), - * only ZSTD_e_end or ZSTD_e_flush operations are allowed. - * Before starting a new compression job, or changing compression parameters, - * it is required to fully flush internal buffers. - */ -ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective endOp); - - -/* These buffer sizes are softly recommended. - * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. - * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), - * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. - * - * However, note that these recommendations are from the perspective of a C caller program. - * If the streaming interface is invoked from some other language, - * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, - * a major performance rule is to reduce crossing such interface to an absolute minimum. - * It's not rare that performance ends being spent more into the interface, rather than compression itself. - * In which cases, prefer using large buffers, as large as practical, - * for both input and output, to reduce the nb of roundtrips. - */ -ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ -ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ - - -/* ***************************************************************************** - * This following is a legacy streaming API. - * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). - * It is redundant, but remains fully supported. - * Advanced parameters and dictionary compression can only be used through the - * new API. - ******************************************************************************/ - -/*! - * Equivalent to: - * - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - */ -ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); -/*! - * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). - * NOTE: The return value is different. ZSTD_compressStream() returns a hint for - * the next read size (if non-zero and not an error). ZSTD_compressStream2() - * returns the minimum nb of bytes left to flush (if non-zero and not an error). - */ -ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); -/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ -ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); -/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ -ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); - - -/*-*************************************************************************** -* Streaming decompression - HowTo -* -* A ZSTD_DStream object is required to track streaming operations. -* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. -* ZSTD_DStream objects can be re-used multiple times. -* -* Use ZSTD_initDStream() to start a new decompression operation. -* @return : recommended first input size -* Alternatively, use advanced API to set specific properties. -* -* Use ZSTD_decompressStream() repetitively to consume your input. -* The function will update both `pos` fields. -* If `input.pos < input.size`, some input has not been consumed. -* It's up to the caller to present again remaining data. -* The function tries to flush all data decoded immediately, respecting output buffer size. -* If `output.pos < output.size`, decoder has flushed everything it could. -* But if `output.pos == output.size`, there might be some data left within internal buffers., -* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. -* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. -* @return : 0 when a frame is completely decoded and fully flushed, -* or an error code, which can be tested using ZSTD_isError(), -* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : -* the return value is a suggested next input size (just a hint for better latency) -* that will never request more than the remaining frame size. -* *******************************************************************************/ - -typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ - /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ -/*===== ZSTD_DStream management functions =====*/ -ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); -ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); - -/*===== Streaming decompression functions =====*/ - -/* This function is redundant with the advanced API and equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_refDDict(zds, NULL); - */ -ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); - -ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); - -ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ -ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ - - -/************************** -* Simple dictionary API -***************************/ -/*! ZSTD_compress_usingDict() : - * Compression at an explicit compression level using a Dictionary. - * A dictionary can be any arbitrary data segment (also called a prefix), - * or a buffer with specified information (see dictBuilder/zdict.h). - * Note : This function loads the dictionary, resulting in significant startup delay. - * It's intended for a dictionary used only once. - * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ -ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - int compressionLevel); - -/*! ZSTD_decompress_usingDict() : - * Decompression using a known Dictionary. - * Dictionary must be identical to the one used during compression. - * Note : This function loads the dictionary, resulting in significant startup delay. - * It's intended for a dictionary used only once. - * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ -ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize); - - -/*********************************** - * Bulk processing dictionary API - **********************************/ -typedef struct ZSTD_CDict_s ZSTD_CDict; - -/*! ZSTD_createCDict() : - * When compressing multiple messages or blocks using the same dictionary, - * it's recommended to digest the dictionary only once, since it's a costly operation. - * ZSTD_createCDict() will create a state from digesting a dictionary. - * The resulting state can be used for future compression operations with very limited startup cost. - * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict. - * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content. - * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer, - * in which case the only thing that it transports is the @compressionLevel. - * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, - * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, - int compressionLevel); - -/*! ZSTD_freeCDict() : - * Function frees memory allocated by ZSTD_createCDict(). */ -ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); - -/*! ZSTD_compress_usingCDict() : - * Compression using a digested Dictionary. - * Recommended when same dictionary is used multiple times. - * Note : compression level is _decided at dictionary creation time_, - * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ -ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict); - - -typedef struct ZSTD_DDict_s ZSTD_DDict; - -/*! ZSTD_createDDict() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); - -/*! ZSTD_freeDDict() : - * Function frees memory allocated with ZSTD_createDDict() */ -ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); - -/*! ZSTD_decompress_usingDDict() : - * Decompression using a digested Dictionary. - * Recommended when same dictionary is used multiple times. */ -ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_DDict* ddict); - - -/******************************** - * Dictionary helper functions - *******************************/ - -/*! ZSTD_getDictID_fromDict() : - * Provides the dictID stored within dictionary. - * if @return == 0, the dictionary is not conformant with Zstandard specification. - * It can still be loaded, but as a content-only dictionary. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); - -/*! ZSTD_getDictID_fromDDict() : - * Provides the dictID of the dictionary loaded into `ddict`. - * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. - * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); - -/*! ZSTD_getDictID_fromFrame() : - * Provides the dictID required to decompressed the frame stored within `src`. - * If @return == 0, the dictID could not be decoded. - * This could for one of the following reasons : - * - The frame does not require a dictionary to be decoded (most common case). - * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. - * Note : this use case also happens when using a non-conformant dictionary. - * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). - * - This is not a Zstandard frame. - * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); - - -/******************************************************************************* - * Advanced dictionary and prefix API - * - * This API allows dictionaries to be used with ZSTD_compress2(), - * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and - * only reset with the context is reset with ZSTD_reset_parameters or - * ZSTD_reset_session_and_parameters. Prefixes are single-use. - ******************************************************************************/ - - -/*! ZSTD_CCtx_loadDictionary() : - * Create an internal CDict from `dict` buffer. - * Decompression will have to use same dictionary. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary, - * meaning "return to no-dictionary mode". - * Note 1 : Dictionary is sticky, it will be used for all future compressed frames. - * To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters). - * Note 2 : Loading a dictionary involves building tables. - * It's also a CPU consuming operation, with non-negligible impact on latency. - * Tables are dependent on compression parameters, and for this reason, - * compression parameters can no longer be changed after loading a dictionary. - * Note 3 :`dict` content will be copied internally. - * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead. - * In such a case, dictionary buffer must outlive its users. - * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() - * to precisely select how dictionary content must be interpreted. */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); - -/*! ZSTD_CCtx_refCDict() : - * Reference a prepared dictionary, to be used for all next compressed frames. - * Note that compression parameters are enforced from within CDict, - * and supersede any compression parameter previously set within CCtx. - * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. - * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. - * The dictionary will remain valid for future compressed frames using same CCtx. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special : Referencing a NULL CDict means "return to no-dictionary mode". - * Note 1 : Currently, only one dictionary can be managed. - * Referencing a new dictionary effectively "discards" any previous one. - * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ -ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); - -/*! ZSTD_CCtx_refPrefix() : - * Reference a prefix (single-usage dictionary) for next compressed frame. - * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). - * Decompression will need same prefix to properly regenerate data. - * Compressing with a prefix is similar in outcome as performing a diff and compressing it, - * but performs much faster, especially during decompression (compression speed is tunable with compression level). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary - * Note 1 : Prefix buffer is referenced. It **must** outlive compression. - * Its content must remain unmodified during compression. - * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, - * ensure that the window size is large enough to contain the entire source. - * See ZSTD_c_windowLog. - * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. - * It's a CPU consuming operation, with non-negligible impact on latency. - * If there is a need to use the same prefix multiple times, consider loadDictionary instead. - * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). - * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ -ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, - const void* prefix, size_t prefixSize); - -/*! ZSTD_DCtx_loadDictionary() : - * Create an internal DDict from dict buffer, - * to be used to decompress next frames. - * The dictionary remains valid for all future frames, until explicitly invalidated. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, - * meaning "return to no-dictionary mode". - * Note 1 : Loading a dictionary involves building tables, - * which has a non-negligible impact on CPU usage and latency. - * It's recommended to "load once, use many times", to amortize the cost - * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading. - * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead. - * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of - * how dictionary content is loaded and interpreted. - */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); - -/*! ZSTD_DCtx_refDDict() : - * Reference a prepared dictionary, to be used to decompress next frames. - * The dictionary remains active for decompression of future frames using same DCtx. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : Currently, only one dictionary can be managed. - * Referencing a new dictionary effectively "discards" any previous one. - * Special: referencing a NULL DDict means "return to no-dictionary mode". - * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. - */ -ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); - -/*! ZSTD_DCtx_refPrefix() : - * Reference a prefix (single-usage dictionary) to decompress next frame. - * This is the reverse operation of ZSTD_CCtx_refPrefix(), - * and must use the same prefix as the one used during compression. - * Prefix is **only used once**. Reference is discarded at end of frame. - * End of frame is reached when ZSTD_decompressStream() returns 0. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary - * Note 2 : Prefix buffer is referenced. It **must** outlive decompression. - * Prefix buffer must remain unmodified up to the end of frame, - * reached when ZSTD_decompressStream() returns 0. - * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent). - * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section) - * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. - * A full dictionary is more costly, as it requires building tables. - */ -ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, - const void* prefix, size_t prefixSize); - -/* === Memory management === */ - -/*! ZSTD_sizeof_*() : - * These functions give the _current_ memory usage of selected object. - * Note that object memory usage can evolve (increase or decrease) over time. */ -ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); -ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); -ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); -ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); -ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); - -#endif /* ZSTD_H_235446 */ - - -/* ************************************************************************************** - * ADVANCED AND EXPERIMENTAL FUNCTIONS - **************************************************************************************** - * The definitions in the following section are considered experimental. - * They are provided for advanced scenarios. - * They should never be used with a dynamic library, as prototypes may change in the future. - * Use them only in association with static linking. - * ***************************************************************************************/ - -#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) -#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY - -/**************************************************************************************** - * experimental API (static linking only) - **************************************************************************************** - * The following symbols and constants - * are not planned to join "stable API" status in the near future. - * They can still change in future versions. - * Some of them are planned to remain in the static_only section indefinitely. - * Some of them might be removed in the future (especially when redundant with existing stable functions) - * ***************************************************************************************/ - -#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */ -#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2) -#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */ -#define ZSTD_SKIPPABLEHEADERSIZE 8 - -/* compression parameter bounds */ -#define ZSTD_WINDOWLOG_MAX_32 30 -#define ZSTD_WINDOWLOG_MAX_64 31 -#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) -#define ZSTD_WINDOWLOG_MIN 10 -#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) -#define ZSTD_HASHLOG_MIN 6 -#define ZSTD_CHAINLOG_MAX_32 29 -#define ZSTD_CHAINLOG_MAX_64 30 -#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) -#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN -#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) -#define ZSTD_SEARCHLOG_MIN 1 -#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ -#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */ -#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX -#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ -#define ZSTD_STRATEGY_MIN ZSTD_fast -#define ZSTD_STRATEGY_MAX ZSTD_btultra2 - - -#define ZSTD_OVERLAPLOG_MIN 0 -#define ZSTD_OVERLAPLOG_MAX 9 - -#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame - * requiring larger than (1< 3, then this is seqDef.offset - 3 - * If seqDef.offset < 3, then this is the corresponding repeat offset - * But if seqDef.offset < 3 and litLength == 0, this is the - * repeat offset before the corresponding repeat offset - * And if seqDef.offset == 3 and litLength == 0, this is the - * most recent repeat offset - 1 - */ - unsigned int offset; - unsigned int litLength; /* Literal length */ - unsigned int matchLength; /* Match length */ - /* 0 when seq not rep and seqDef.offset otherwise - * when litLength == 0 this will be <= 4, otherwise <= 3 like normal - */ - unsigned int rep; -} ZSTD_Sequence; - -typedef struct { - unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ - unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ - unsigned hashLog; /**< dispatch table : larger == faster, more memory */ - unsigned searchLog; /**< nb of searches : larger == more compression, slower */ - unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ - unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ - ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ -} ZSTD_compressionParameters; - -typedef struct { - int contentSizeFlag; /**< 1: content size will be in frame header (when known) */ - int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */ - int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */ -} ZSTD_frameParameters; - -typedef struct { - ZSTD_compressionParameters cParams; - ZSTD_frameParameters fParams; -} ZSTD_parameters; - -typedef enum { - ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ - ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ - ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ -} ZSTD_dictContentType_e; - -typedef enum { - ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ - ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ -} ZSTD_dictLoadMethod_e; - -typedef enum { - ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ - ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. - * Useful to save 4 bytes per generated frame. - * Decoder cannot recognise automatically this format, requiring this instruction. */ -} ZSTD_format_e; - -typedef enum { - /* Note: this enum and the behavior it controls are effectively internal - * implementation details of the compressor. They are expected to continue - * to evolve and should be considered only in the context of extremely - * advanced performance tuning. - * - * Zstd currently supports the use of a CDict in three ways: - * - * - The contents of the CDict can be copied into the working context. This - * means that the compression can search both the dictionary and input - * while operating on a single set of internal tables. This makes - * the compression faster per-byte of input. However, the initial copy of - * the CDict's tables incurs a fixed cost at the beginning of the - * compression. For small compressions (< 8 KB), that copy can dominate - * the cost of the compression. - * - * - The CDict's tables can be used in-place. In this model, compression is - * slower per input byte, because the compressor has to search two sets of - * tables. However, this model incurs no start-up cost (as long as the - * working context's tables can be reused). For small inputs, this can be - * faster than copying the CDict's tables. - * - * - The CDict's tables are not used at all, and instead we use the working - * context alone to reload the dictionary and use params based on the source - * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). - * This method is effective when the dictionary sizes are very small relative - * to the input size, and the input size is fairly large to begin with. - * - * Zstd has a simple internal heuristic that selects which strategy to use - * at the beginning of a compression. However, if experimentation shows that - * Zstd is making poor choices, it is possible to override that choice with - * this enum. - */ - ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ - ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ - ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ - ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ -} ZSTD_dictAttachPref_e; - -typedef enum { - ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. - * Negative compression levels will be uncompressed, and positive compression - * levels will be compressed. */ - ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be - * emitted if Huffman compression is not profitable. */ - ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ -} ZSTD_literalCompressionMode_e; - - -/*************************************** -* Frame size functions -***************************************/ - -/*! ZSTD_findDecompressedSize() : - * `src` should point to the start of a series of ZSTD encoded and/or skippable frames - * `srcSize` must be the _exact_ size of this series - * (i.e. there should be a frame boundary at `src + srcSize`) - * @return : - decompressed size of all data in all successive frames - * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN - * - if an error occurred: ZSTD_CONTENTSIZE_ERROR - * - * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * note 2 : decompressed size is always present when compression is done with ZSTD_compress() - * note 3 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure result fits within application's authorized limits. - * Each application can set its own limits. - * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to - * read each contained frame header. This is fast as most of the data is skipped, - * however it does mean that all frame data must be present and valid. */ -ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); - -/*! ZSTD_decompressBound() : - * `src` should point to the start of a series of ZSTD encoded and/or skippable frames - * `srcSize` must be the _exact_ size of this series - * (i.e. there should be a frame boundary at `src + srcSize`) - * @return : - upper-bound for the decompressed size of all data in all successive frames - * - if an error occured: ZSTD_CONTENTSIZE_ERROR - * - * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. - * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. - * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value. - * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: - * upper-bound = # blocks * min(128 KB, Window_Size) - */ -ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); - -/*! ZSTD_frameHeaderSize() : - * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. - * @return : size of the Frame Header, - * or an error code (if srcSize is too small) */ -ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); - -/*! ZSTD_getSequences() : - * Extract sequences from the sequence store - * zc can be used to insert custom compression params. - * This function invokes ZSTD_compress2 - * @return : number of sequences extracted - */ -ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize); - - -/*************************************** -* Memory management -***************************************/ - -/*! ZSTD_estimate*() : - * These functions make it possible to estimate memory usage of a future - * {D,C}Ctx, before its creation. - * - * ZSTD_estimateCCtxSize() will provide a budget large enough for any - * compression level up to selected one. Unlike ZSTD_estimateCStreamSize*(), - * this estimate does not include space for a window buffer, so this estimate - * is guaranteed to be enough for single-shot compressions, but not streaming - * compressions. It will however assume the input may be arbitrarily large, - * which is the worst case. If srcSize is known to always be small, - * ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. - * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with - * ZSTD_getCParams() to create cParams from compressionLevel. - * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with - * ZSTD_CCtxParams_setParameter(). - * - * Note: only single-threaded compression is supported. This function will - * return an error code if ZSTD_c_nbWorkers is >= 1. */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); -ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); -ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); - -/*! ZSTD_estimateCStreamSize() : - * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one. - * It will also consider src size to be arbitrarily "large", which is worst case. - * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. - * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. - * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. - * Note : CStream size estimation is only correct for single-threaded compression. - * ZSTD_DStream memory budget depends on window Size. - * This information can be passed manually, using ZSTD_estimateDStreamSize, - * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); - * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), - * an internal ?Dict will be created, which additional size is not estimated here. - * In this case, get total size by adding ZSTD_estimate?DictSize */ -ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); -ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); -ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize); -ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); - -/*! ZSTD_estimate?DictSize() : - * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). - * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). - * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. - */ -ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); -ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); - -/*! ZSTD_initStatic*() : - * Initialize an object using a pre-allocated fixed-size buffer. - * workspace: The memory area to emplace the object into. - * Provided pointer *must be 8-bytes aligned*. - * Buffer must outlive object. - * workspaceSize: Use ZSTD_estimate*Size() to determine - * how large workspace must be to support target scenario. - * @return : pointer to object (same address as workspace, just different type), - * or NULL if error (size too small, incorrect alignment, etc.) - * Note : zstd will never resize nor malloc() when using a static buffer. - * If the object requires more memory than available, - * zstd will just error out (typically ZSTD_error_memory_allocation). - * Note 2 : there is no corresponding "free" function. - * Since workspace is allocated externally, it must be freed externally too. - * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level - * into its associated cParams. - * Limitation 1 : currently not compatible with internal dictionary creation, triggered by - * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). - * Limitation 2 : static cctx currently not compatible with multi-threading. - * Limitation 3 : static dctx is incompatible with legacy support. - */ -ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ - -ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ - -ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict( - void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams); - -ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( - void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType); - - -/*! Custom memory allocation : - * These prototypes make it possible to pass your own allocation/free functions. - * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. - * All allocation/free operations will be completed using these custom variants instead of regular ones. - */ -typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); -typedef void (*ZSTD_freeFunction) (void* opaque, void* address); -typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; -static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ - -ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); - -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, - ZSTD_customMem customMem); - -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_customMem customMem); - - - -/*************************************** -* Advanced compression functions -***************************************/ - -/*! ZSTD_createCDict_byReference() : - * Create a digested dictionary for compression - * Dictionary content is just referenced, not duplicated. - * As a consequence, `dictBuffer` **must** outlive CDict, - * and its content must remain unmodified throughout the lifetime of CDict. - * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); - -/*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. - * `estimatedSrcSize` value is optional, select 0 if not known */ -ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - -/*! ZSTD_getParams() : - * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. - * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ -ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - -/*! ZSTD_checkCParams() : - * Ensure param values remain within authorized range. - * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */ -ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); - -/*! ZSTD_adjustCParams() : - * optimize params for a given `srcSize` and `dictSize`. - * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN. - * `dictSize` must be `0` when there is no dictionary. - * cPar can be invalid : all parameters will be clamped within valid range in the @return struct. - * This function never fails (wide contract) */ -ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); - -/*! ZSTD_compress_advanced() : - * Note : this function is now DEPRECATED. - * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */ -ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - ZSTD_parameters params); - -/*! ZSTD_compress_usingCDict_advanced() : - * Note : this function is now REDUNDANT. - * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning in some future version */ -ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams); - - -/*! ZSTD_CCtx_loadDictionary_byReference() : - * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. - * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); - -/*! ZSTD_CCtx_loadDictionary_advanced() : - * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over - * how to load the dictionary (by copy ? by reference ?) - * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_CCtx_refPrefix_advanced() : - * Same as ZSTD_CCtx_refPrefix(), but gives finer control over - * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); - -/* === experimental parameters === */ -/* these parameters can be used with ZSTD_setParameter() - * they are not guaranteed to remain supported in the future */ - - /* Enables rsyncable mode, - * which makes compressed files more rsync friendly - * by adding periodic synchronization points to the compressed data. - * The target average block size is ZSTD_c_jobSize / 2. - * It's possible to modify the job size to increase or decrease - * the granularity of the synchronization point. - * Once the jobSize is smaller than the window size, - * it will result in compression ratio degradation. - * NOTE 1: rsyncable mode only works when multithreading is enabled. - * NOTE 2: rsyncable performs poorly in combination with long range mode, - * since it will decrease the effectiveness of synchronization points, - * though mileage may vary. - * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s. - * If the selected compression level is already running significantly slower, - * the overall speed won't be significantly impacted. - */ - #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1 - -/* Select a compression format. - * The value must be of type ZSTD_format_e. - * See ZSTD_format_e enum definition for details */ -#define ZSTD_c_format ZSTD_c_experimentalParam2 - -/* Force back-reference distances to remain < windowSize, - * even when referencing into Dictionary content (default:0) */ -#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3 - -/* Controls whether the contents of a CDict - * are used in place, or copied into the working context. - * Accepts values from the ZSTD_dictAttachPref_e enum. - * See the comments on that enum for an explanation of the feature. */ -#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 - -/* Controls how the literals are compressed (default is auto). - * The value must be of type ZSTD_literalCompressionMode_e. - * See ZSTD_literalCompressionMode_t enum definition for details. - */ -#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 - -/* Tries to fit compressed block size to be around targetCBlockSize. - * No target when targetCBlockSize == 0. - * There is no guarantee on compressed block size (default:0) */ -#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6 - -/* User's best guess of source size. - * Hint is not valid when srcSizeHint == 0. - * There is no guarantee that hint is close to actual source size, - * but compression ratio may regress significantly if guess considerably underestimates */ -#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 - -/*! ZSTD_CCtx_getParameter() : - * Get the requested compression parameter value, selected by enum ZSTD_cParameter, - * and store it into int* value. - * @return : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); - - -/*! ZSTD_CCtx_params : - * Quick howto : - * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure - * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into - * an existing ZSTD_CCtx_params structure. - * This is similar to - * ZSTD_CCtx_setParameter(). - * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to - * an existing CCtx. - * These parameters will be applied to - * all subsequent frames. - * - ZSTD_compressStream2() : Do compression using the CCtx. - * - ZSTD_freeCCtxParams() : Free the memory. - * - * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() - * for static allocation of CCtx for single-threaded compression. - */ -ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); -ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); - -/*! ZSTD_CCtxParams_reset() : - * Reset params to default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); - -/*! ZSTD_CCtxParams_init() : - * Initializes the compression parameters of cctxParams according to - * compression level. All other parameters are reset to their default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); - -/*! ZSTD_CCtxParams_init_advanced() : - * Initializes the compression and frame parameters of cctxParams according to - * params. All other parameters are reset to their default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); - -/*! ZSTD_CCtxParams_setParameter() : - * Similar to ZSTD_CCtx_setParameter. - * Set one compression parameter, selected by enum ZSTD_cParameter. - * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); - -/*! ZSTD_CCtxParams_getParameter() : - * Similar to ZSTD_CCtx_getParameter. - * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); - -/*! ZSTD_CCtx_setParametersUsingCCtxParams() : - * Apply a set of ZSTD_CCtx_params to the compression context. - * This can be done even after compression is started, - * if nbWorkers==0, this will have no impact until a new compression is started. - * if nbWorkers>=1, new parameters will be picked up at next job, - * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). - */ -ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( - ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); - -/*! ZSTD_compressStream2_simpleArgs() : - * Same as ZSTD_compressStream2(), - * but using only integral types as arguments. - * This variant might be helpful for binders from dynamic languages - * which have troubles handling structures containing memory pointers. - */ -ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs ( - ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos, - ZSTD_EndDirective endOp); - - -/*************************************** -* Advanced decompression functions -***************************************/ - -/*! ZSTD_isFrame() : - * Tells if the content of `buffer` starts with a valid Frame Identifier. - * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. - * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. - * Note 3 : Skippable Frame Identifiers are considered valid. */ -ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size); - -/*! ZSTD_createDDict_byReference() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * Dictionary content is referenced, and therefore stays in dictBuffer. - * It is important that dictBuffer outlives DDict, - * it must remain read accessible throughout the lifetime of DDict */ -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); - -/*! ZSTD_DCtx_loadDictionary_byReference() : - * Same as ZSTD_DCtx_loadDictionary(), - * but references `dict` content instead of copying it into `dctx`. - * This saves memory if `dict` remains around., - * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); - -/*! ZSTD_DCtx_loadDictionary_advanced() : - * Same as ZSTD_DCtx_loadDictionary(), - * but gives direct control over - * how to load the dictionary (by copy ? by reference ?) - * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_DCtx_refPrefix_advanced() : - * Same as ZSTD_DCtx_refPrefix(), but gives finer control over - * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_DCtx_setMaxWindowSize() : - * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. - * This protects a decoder context from reserving too much memory for itself (potential attack scenario). - * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. - * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) - * @return : 0, or an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); - -/* ZSTD_d_format - * experimental parameter, - * allowing selection between ZSTD_format_e input compression formats - */ -#define ZSTD_d_format ZSTD_d_experimentalParam1 - -/*! ZSTD_DCtx_setFormat() : - * Instruct the decoder context about what kind of data to decode next. - * This instruction is mandatory to decode data without a fully-formed header, - * such ZSTD_f_zstd1_magicless for example. - * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); - -/*! ZSTD_decompressStream_simpleArgs() : - * Same as ZSTD_decompressStream(), - * but using only integral types as arguments. - * This can be helpful for binders from dynamic languages - * which have troubles handling structures containing memory pointers. - */ -ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( - ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos); - - -/******************************************************************** -* Advanced streaming functions -* Warning : most of these functions are now redundant with the Advanced API. -* Once Advanced API reaches "stable" status, -* redundant functions will be deprecated, and then at some point removed. -********************************************************************/ - -/*===== Advanced Streaming compression functions =====*/ -/**! ZSTD_initCStream_srcSize() : - * This function is deprecated, and equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * - * pledgedSrcSize must be correct. If it is not known at init time, use - * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, - * "0" also disables frame content size field. It may be enabled in the future. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, - int compressionLevel, - unsigned long long pledgedSrcSize); - -/**! ZSTD_initCStream_usingDict() : - * This function is deprecated, and is equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); - * - * Creates of an internal CDict (incompatible with static CCtx), except if - * dict == NULL or dictSize < 8, in which case no dict is used. - * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if - * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, - int compressionLevel); - -/**! ZSTD_initCStream_advanced() : - * This function is deprecated, and is approximately equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * // Pseudocode: Set each zstd parameter and leave the rest as-is. - * for ((param, value) : params) { - * ZSTD_CCtx_setParameter(zcs, param, value); - * } - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); - * - * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. - * pledgedSrcSize must be correct. - * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_advanced(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, - ZSTD_parameters params, - unsigned long long pledgedSrcSize); - -/**! ZSTD_initCStream_usingCDict() : - * This function is deprecated, and equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, cdict); - * - * note : cdict will just be referenced, and must outlive compression session - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); - -/**! ZSTD_initCStream_usingCDict_advanced() : - * This function is DEPRECATED, and is approximately equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * // Pseudocode: Set each zstd frame parameter and leave the rest as-is. - * for ((fParam, value) : fParams) { - * ZSTD_CCtx_setParameter(zcs, fParam, value); - * } - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * ZSTD_CCtx_refCDict(zcs, cdict); - * - * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. - * pledgedSrcSize must be correct. If srcSize is not known at init time, use - * value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams, - unsigned long long pledgedSrcSize); - -/*! ZSTD_resetCStream() : - * This function is deprecated, and is equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * - * start a new frame, using same parameters from previous frame. - * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. - * Note that zcs must be init at least once before using ZSTD_resetCStream(). - * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. - * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. - * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, - * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); - - -typedef struct { - unsigned long long ingested; /* nb input bytes read and buffered */ - unsigned long long consumed; /* nb input bytes actually compressed */ - unsigned long long produced; /* nb of compressed bytes generated and buffered */ - unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ - unsigned currentJobID; /* MT only : latest started job nb */ - unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ -} ZSTD_frameProgression; - -/* ZSTD_getFrameProgression() : - * tells how much data has been ingested (read from input) - * consumed (input actually compressed) and produced (output) for current frame. - * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. - * Aggregates progression inside active worker threads. - */ -ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); - -/*! ZSTD_toFlushNow() : - * Tell how many bytes are ready to be flushed immediately. - * Useful for multithreading scenarios (nbWorkers >= 1). - * Probe the oldest active job, defined as oldest job not yet entirely flushed, - * and check its output buffer. - * @return : amount of data stored in oldest job and ready to be flushed immediately. - * if @return == 0, it means either : - * + there is no active job (could be checked with ZSTD_frameProgression()), or - * + oldest job is still actively compressing data, - * but everything it has produced has also been flushed so far, - * therefore flush speed is limited by production speed of oldest job - * irrespective of the speed of concurrent (and newer) jobs. - */ -ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); - - -/*===== Advanced Streaming decompression functions =====*/ -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_loadDictionary(zds, dict, dictSize); - * - * note: no dictionary will be used if dict == NULL or dictSize < 8 - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); - -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_refDDict(zds, ddict); - * - * note : ddict is referenced, it must outlive decompression session - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); - -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * - * re-use decompression parameters from previous init; saves dictionary loading - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); - - -/********************************************************************* -* Buffer-less and synchronous inner streaming functions -* -* This is an advanced API, giving full control over buffer management, for users which need direct control over memory. -* But it's also a complex one, with several restrictions, documented below. -* Prefer normal streaming API for an easier experience. -********************************************************************* */ - -/** - Buffer-less streaming compression (synchronous mode) - - A ZSTD_CCtx object is required to track streaming operations. - Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. - ZSTD_CCtx object can be re-used multiple times within successive compression operations. - - Start by initializing a context. - Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, - or ZSTD_compressBegin_advanced(), for finer parameter control. - It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() - - Then, consume your input using ZSTD_compressContinue(). - There are some important considerations to keep in mind when using this advanced function : - - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. - - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. - - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. - Worst case evaluation is provided by ZSTD_compressBound(). - ZSTD_compressContinue() doesn't guarantee recover after a failed compression. - - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). - It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) - - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. - In which case, it will "discard" the relevant memory section from its history. - - Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. - It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. - Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. - - `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again. -*/ - -/*===== Buffer-less streaming compression functions =====*/ -ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); -ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); -ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ -ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ - -ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); - - -/*- - Buffer-less streaming decompression (synchronous mode) - - A ZSTD_DCtx object is required to track streaming operations. - Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. - A ZSTD_DCtx object can be re-used multiple times. - - First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). - Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. - Data fragment must be large enough to ensure successful decoding. - `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. - @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. - >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. - errorCode, which can be tested using ZSTD_isError(). - - It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, - such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). - Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. - As a consequence, check that values remain within valid application range. - For example, do not allocate memory blindly, check that `windowSize` is within expectation. - Each application can set its own limits, depending on local restrictions. - For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. - - ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. - ZSTD_decompressContinue() is very sensitive to contiguity, - if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, - or that previous contiguous segment is large enough to properly handle maximum back-reference distance. - There are multiple ways to guarantee this condition. - - The most memory efficient way is to use a round buffer of sufficient size. - Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), - which can @return an error code if required value is too large for current system (in 32-bits mode). - In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, - up to the moment there is not enough room left in the buffer to guarantee decoding another full block, - which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. - At which point, decoding can resume from the beginning of the buffer. - Note that already decoded data stored in the buffer should be flushed before being overwritten. - - There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. - - Finally, if you control the compression process, you can also ignore all buffer size rules, - as long as the encoder and decoder progress in "lock-step", - aka use exactly the same buffer sizes, break contiguity at the same place, etc. - - Once buffers are setup, start decompression, with ZSTD_decompressBegin(). - If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). - - Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. - ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. - - @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). - It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. - It can also be an error code, which can be tested with ZSTD_isError(). - - A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. - Context can then be reset to start a new decompression. - - Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). - This information is not required to properly decode a frame. - - == Special case : skippable frames == - - Skippable frames allow integration of user-defined data into a flow of concatenated frames. - Skippable frames will be ignored (skipped) by decompressor. - The format of skippable frames is as follows : - a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F - b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits - c) Frame Content - any content (User Data) of length equal to Frame Size - For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. - For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. -*/ - -/*===== Buffer-less streaming decompression functions =====*/ -typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; -typedef struct { - unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ - unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ - unsigned blockSizeMax; - ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ - unsigned headerSize; - unsigned dictID; - unsigned checksumFlag; -} ZSTD_frameHeader; - -/*! ZSTD_getFrameHeader() : - * decode Frame Header, or requires larger `srcSize`. - * @return : 0, `zfhPtr` is correctly filled, - * >0, `srcSize` is too small, value is wanted `srcSize` amount, - * or an error code, which can be tested using ZSTD_isError() */ -ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ -/*! ZSTD_getFrameHeader_advanced() : - * same as ZSTD_getFrameHeader(), - * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ -ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); -ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ - -ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); -ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); - -ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); - -/* misc */ -ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); -typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; -ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); - - - - -/* ============================ */ -/** Block level API */ -/* ============================ */ - -/*! - Block functions produce and decode raw zstd blocks, without frame metadata. - Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes). - But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes. - - A few rules to respect : - - Compressing and decompressing require a context structure - + Use ZSTD_createCCtx() and ZSTD_createDCtx() - - It is necessary to init context before starting - + compression : any ZSTD_compressBegin*() variant, including with dictionary - + decompression : any ZSTD_decompressBegin*() variant, including with dictionary - + copyCCtx() and copyDCtx() can be used too - - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB - + If input is larger than a block size, it's necessary to split input data into multiple blocks - + For inputs larger than a single block, consider using regular ZSTD_compress() instead. - Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block. - - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) ! - ===> In which case, nothing is produced into `dst` ! - + User __must__ test for such outcome and deal directly with uncompressed data - + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0. - Doing so would mess up with statistics history, leading to potential data corruption. - + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !! - + In case of multiple successive blocks, should some of them be uncompressed, - decoder must be informed of their existence in order to follow proper history. - Use ZSTD_insertBlock() for such a case. -*/ - -/*===== Raw zstd block functions =====*/ -ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); -ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */ - - -#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ - -#if defined (__cplusplus) -} -#endif diff --git a/lib/common/error_private.h b/lib/common/error_private.h index 78a9780debe..ced1a3ba978 100644 --- a/lib/common/error_private.h +++ b/lib/common/error_private.h @@ -57,6 +57,10 @@ ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } +/* check and forward error code */ +#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e +#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } + /*-**************************************** * Error Strings diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c index e85a3ba4456..9f948e1c046 100644 --- a/lib/common/fse_decompress.c +++ b/lib/common/fse_decompress.c @@ -31,11 +31,6 @@ #define FSE_isError ERR_isError #define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ -/* check and forward error code */ -#ifndef CHECK_F -#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } -#endif - /* ************************************************************** * Templates diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index ce80f8c5639..899883bc3af 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -248,6 +248,14 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e } } +MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + size_t const length = MIN(dstCapacity, srcSize); + if (length > 0) { + memcpy(dst, src, length); + } + return length; +} /*-******************************************* * Private declarations diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c index 8f603b02f16..e09b646df11 100644 --- a/lib/compress/fse_compress.c +++ b/lib/compress/fse_compress.c @@ -625,11 +625,6 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize, size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } -#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e -#ifndef CHECK_F -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } -#endif - /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). * `wkspSize` size must be `(1< 0) { - memcpy(dst, src, length); - } - return length; -} -#endif - /** ZSTD_compressStream_generic(): * internal function for all *compressStream*() variants * non-static, because can be called from zstdmt_compress.c diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 84703e5a49f..ac93ed0bf3a 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1498,17 +1498,6 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) /* ***** Decompression ***** */ -#ifndef ZSTD_COMPRESS_H /* zstd_compress.c has the same function */ -MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) -{ - size_t const length = MIN(dstCapacity, srcSize); - if (length > 0) { - memcpy(dst, src, length); - } - return length; -} -#endif - size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { const char* const src = (const char*)input->src; From a93fadfcd925012d2754c1962c486a7b65fc16e9 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 11:25:16 +0200 Subject: [PATCH 270/402] Further replication removed `CHECK_F` is now in `error_private.h`. Minor tidy. --- lib/compress/huf_compress.c | 4 ---- lib/decompress/huf_decompress.c | 3 --- lib/decompress/zstd_decompress.c | 1 - 3 files changed, 8 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index ed69dfd03ca..5cab31d042f 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -40,10 +40,6 @@ ****************************************************************/ #define HUF_isError ERR_isError #define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ -#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e -#ifndef CHECK_F -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } -#endif /* ************************************************************** diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index a2478b4c78a..ab5db481c36 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -41,9 +41,6 @@ * Error Management ****************************************************************/ #define HUF_isError ERR_isError -#ifndef CHECK_F -#define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; } -#endif /* ************************************************************** diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index a7fcd57fea5..6ef156b658d 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1499,7 +1499,6 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) /* ***** Decompression ***** */ - static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize) { return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR; From 59812afac795ed05698c700705199693c2e8c611 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 13:19:52 +0200 Subject: [PATCH 271/402] Improved documentation --- contrib/single_file_decoder/README.md | 33 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/contrib/single_file_decoder/README.md b/contrib/single_file_decoder/README.md index 7692ebbf6a4..b8a44a3ecb7 100644 --- a/contrib/single_file_decoder/README.md +++ b/contrib/single_file_decoder/README.md @@ -1,26 +1,33 @@ -# Single File Zstandard Decompression Library +# Single File Zstandard Libraries The script `combine.sh` creates an _amalgamated_ source file that can be used with or without `zstd.h`. This isn't a _header-only_ file but it does offer a similar level of simplicity when integrating into a project. +All it now takes to support Zstd in your own projects is the addition of a single file, two if using the header, with no configuration or further build steps. + +Decompressor +------------ + +This is the most common use case. The decompression library is small, adding, for example, 26kB to an Emscripten compiled WebAssembly project. Native implementations add a little more, 40-70kB depending on the compiler and platform. + Create `zstddeclib.c` from the Zstd source using: ``` -cd zstd/contrib/single_file_decoder +cd zstd/contrib/single_file_libs ./combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c ``` Then add the resulting file to your project (see the [example files](examples)). -`create_single_file_decoder.sh` will run the above script, creating file `zstddeclib.c`. -`build_decoder_test.sh` will create the decoder, then compile and test the library. +`create_single_file_decoder.sh` will run the above script, creating the file `zstddeclib.c` (`build_decoder_test.sh` will also create `zstddeclib.c`, then compile and test the result). -Why? ----- +Full Library +------------ -Because all it now takes to support decompressing Zstd is the addition of a single file, two if using the header, with no configuration or further build steps. The library is small, adding, for example, 26kB to an Emscripten compiled WebAssembly project. Native implementations add a little more, 40-70kB depending on the compiler and platform. +The same tool can amalgamate the entire Zstd library for ease of adding both compression and decompression to a project. The [roundtrip example](examples/roundtrip.c) uses the original `zstd.h` with the remaining source files combined into `zstd.c` (currently just over 1MB) created from `zstd-in.c`. As with the standalone decoder the most useful compile flags have already been rolled-in and the resulting file can be added to a project as-is. -Optional Full Library ---------------------- - -The same tool can amalgamate the entire Zstd library for ease of adding both compression and decompression to a project. The [roundtrip example](examples/roundtrip.c) uses the original `zstd.h` with the remaining source files combined into `zstd.c` (currently just over 1MB) created from `zstd-in.c`. As with the standalone decoder the most useful compile flags have already been rolled-in and the resulting files can be added to a project as-is. +Create `zstd.c` from the Zstd source using: +``` +cd zstd/contrib/single_file_libs +combine.sh -r ../../lib -r ../../lib/common -r ../../lib/compress -r ../../lib/decompress -k zstd.h -o zstd.c zstd-in.c +``` +It's possible to create a compressor-only library but since the decompressor is so small in comparison this doesn't bring much of a gain (but for the curious, simply remove the files in the _decompress_ section at the end of `zstd-in.c`). -`create_single_file_library.sh` will run the script to create `zstd.c`. -`build_library_test.sh` will create the library, then compile and test the result. +`create_single_file_library.sh` will run the script to create `zstd.c` (`build_library_test.sh` will also create `zstd.c`, then compile and test the result). From d01e7c2fad7069fd9ddced5f65f76eed1e8f8ac3 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 13:34:19 +0200 Subject: [PATCH 272/402] Renamed directory --- .../.gitignore | 0 .../README.md | 0 .../build_decoder_test.sh | 0 .../build_library_test.sh | 0 .../combine.sh | 0 .../create_single_file_decoder.sh | 0 .../create_single_file_library.sh | 0 .../examples/README.md | 0 .../examples/emscripten.c | 0 .../examples/roundtrip.c | 0 .../examples/shell.html | 0 .../examples/simple.c | 0 .../examples/testcard-dxt1.inl | 0 .../examples/testcard-zstd.inl | 0 .../examples/testcard.png | Bin .../zstd-in.c | 0 .../zstddeclib-in.c | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename contrib/{single_file_decoder => single_file_libs}/.gitignore (100%) rename contrib/{single_file_decoder => single_file_libs}/README.md (100%) rename contrib/{single_file_decoder => single_file_libs}/build_decoder_test.sh (100%) rename contrib/{single_file_decoder => single_file_libs}/build_library_test.sh (100%) rename contrib/{single_file_decoder => single_file_libs}/combine.sh (100%) rename contrib/{single_file_decoder => single_file_libs}/create_single_file_decoder.sh (100%) rename contrib/{single_file_decoder => single_file_libs}/create_single_file_library.sh (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/README.md (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/emscripten.c (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/roundtrip.c (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/shell.html (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/simple.c (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/testcard-dxt1.inl (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/testcard-zstd.inl (100%) rename contrib/{single_file_decoder => single_file_libs}/examples/testcard.png (100%) rename contrib/{single_file_decoder => single_file_libs}/zstd-in.c (100%) rename contrib/{single_file_decoder => single_file_libs}/zstddeclib-in.c (100%) diff --git a/contrib/single_file_decoder/.gitignore b/contrib/single_file_libs/.gitignore similarity index 100% rename from contrib/single_file_decoder/.gitignore rename to contrib/single_file_libs/.gitignore diff --git a/contrib/single_file_decoder/README.md b/contrib/single_file_libs/README.md similarity index 100% rename from contrib/single_file_decoder/README.md rename to contrib/single_file_libs/README.md diff --git a/contrib/single_file_decoder/build_decoder_test.sh b/contrib/single_file_libs/build_decoder_test.sh similarity index 100% rename from contrib/single_file_decoder/build_decoder_test.sh rename to contrib/single_file_libs/build_decoder_test.sh diff --git a/contrib/single_file_decoder/build_library_test.sh b/contrib/single_file_libs/build_library_test.sh similarity index 100% rename from contrib/single_file_decoder/build_library_test.sh rename to contrib/single_file_libs/build_library_test.sh diff --git a/contrib/single_file_decoder/combine.sh b/contrib/single_file_libs/combine.sh similarity index 100% rename from contrib/single_file_decoder/combine.sh rename to contrib/single_file_libs/combine.sh diff --git a/contrib/single_file_decoder/create_single_file_decoder.sh b/contrib/single_file_libs/create_single_file_decoder.sh similarity index 100% rename from contrib/single_file_decoder/create_single_file_decoder.sh rename to contrib/single_file_libs/create_single_file_decoder.sh diff --git a/contrib/single_file_decoder/create_single_file_library.sh b/contrib/single_file_libs/create_single_file_library.sh similarity index 100% rename from contrib/single_file_decoder/create_single_file_library.sh rename to contrib/single_file_libs/create_single_file_library.sh diff --git a/contrib/single_file_decoder/examples/README.md b/contrib/single_file_libs/examples/README.md similarity index 100% rename from contrib/single_file_decoder/examples/README.md rename to contrib/single_file_libs/examples/README.md diff --git a/contrib/single_file_decoder/examples/emscripten.c b/contrib/single_file_libs/examples/emscripten.c similarity index 100% rename from contrib/single_file_decoder/examples/emscripten.c rename to contrib/single_file_libs/examples/emscripten.c diff --git a/contrib/single_file_decoder/examples/roundtrip.c b/contrib/single_file_libs/examples/roundtrip.c similarity index 100% rename from contrib/single_file_decoder/examples/roundtrip.c rename to contrib/single_file_libs/examples/roundtrip.c diff --git a/contrib/single_file_decoder/examples/shell.html b/contrib/single_file_libs/examples/shell.html similarity index 100% rename from contrib/single_file_decoder/examples/shell.html rename to contrib/single_file_libs/examples/shell.html diff --git a/contrib/single_file_decoder/examples/simple.c b/contrib/single_file_libs/examples/simple.c similarity index 100% rename from contrib/single_file_decoder/examples/simple.c rename to contrib/single_file_libs/examples/simple.c diff --git a/contrib/single_file_decoder/examples/testcard-dxt1.inl b/contrib/single_file_libs/examples/testcard-dxt1.inl similarity index 100% rename from contrib/single_file_decoder/examples/testcard-dxt1.inl rename to contrib/single_file_libs/examples/testcard-dxt1.inl diff --git a/contrib/single_file_decoder/examples/testcard-zstd.inl b/contrib/single_file_libs/examples/testcard-zstd.inl similarity index 100% rename from contrib/single_file_decoder/examples/testcard-zstd.inl rename to contrib/single_file_libs/examples/testcard-zstd.inl diff --git a/contrib/single_file_decoder/examples/testcard.png b/contrib/single_file_libs/examples/testcard.png similarity index 100% rename from contrib/single_file_decoder/examples/testcard.png rename to contrib/single_file_libs/examples/testcard.png diff --git a/contrib/single_file_decoder/zstd-in.c b/contrib/single_file_libs/zstd-in.c similarity index 100% rename from contrib/single_file_decoder/zstd-in.c rename to contrib/single_file_libs/zstd-in.c diff --git a/contrib/single_file_decoder/zstddeclib-in.c b/contrib/single_file_libs/zstddeclib-in.c similarity index 100% rename from contrib/single_file_decoder/zstddeclib-in.c rename to contrib/single_file_libs/zstddeclib-in.c From 4e6027f8ca5e9dcd9badc833a7aa28ebec022bbe Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 13:35:19 +0200 Subject: [PATCH 273/402] Fixed-up single-file libs directory --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6965fc043b6..b11d17d135a 100644 --- a/Makefile +++ b/Makefile @@ -109,8 +109,8 @@ contrib: lib $(MAKE) -C contrib/pzstd all $(MAKE) -C contrib/seekable_format/examples all $(MAKE) -C contrib/largeNbDicts all - cd contrib/single_file_decoder/ ; ./build_decoder_test.sh - cd contrib/single_file_decoder/ ; ./build_library_test.sh + cd contrib/single_file_libs/ ; ./build_decoder_test.sh + cd contrib/single_file_libs/ ; ./build_library_test.sh .PHONY: cleanTabs cleanTabs: From 3eaa525138fe98bdfd3d38d266ce3eb5074168e6 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 7 Apr 2020 18:17:59 +0200 Subject: [PATCH 274/402] Fixed clash when projects are already using xxHash Undefing XXH_* macros allows the `.c` to build standalone without clashes. Removing `xxhash.c` and only including the header is the correct usage (according to `XXH_PRIVATE_API`). --- contrib/single_file_libs/zstd-in.c | 21 +++++++++++++-------- contrib/single_file_libs/zstddeclib-in.c | 17 +++++++++++------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/contrib/single_file_libs/zstd-in.c b/contrib/single_file_libs/zstd-in.c index afbab99908d..c3551226411 100644 --- a/contrib/single_file_libs/zstd-in.c +++ b/contrib/single_file_libs/zstd-in.c @@ -1,7 +1,7 @@ /** * \file zstd.c * Single-file Zstandard library. - * + * * Generate using: * \code * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/compress -r ../../lib/decompress -k zstd.h -o zstd.c zstd-in.c @@ -18,19 +18,25 @@ */ /* * Settings to bake for the single library file. - * + * * Note: It's important that none of these affects 'zstd.h' (only the * implementation files we're amalgamating). - * + * * Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also * defined in mem.h (breaking C99 compatibility). - * + * + * Note: the undefs for xxHash allow Zstd's implementation to coinside with with + * standalone xxHash usage (with global defines). + * * Note: multithreading is enabled for all platforms apart from Emscripten. */ #define DEBUGLEVEL 0 #define MEM_MODULE +#undef XXH_NAMESPACE #define XXH_NAMESPACE ZSTD_ +#undef XXH_PRIVATE_API #define XXH_PRIVATE_API +#undef XXH_INLINE_ALL #define XXH_INLINE_ALL #define ZSTD_LEGACY_SUPPORT 0 #define ZSTD_LIB_DICTBUILDER 0 @@ -40,17 +46,16 @@ #define ZSTD_MULTITHREAD #endif -/* common */ +/* lib/common */ #include "debug.c" #include "entropy_common.c" #include "error_private.c" #include "fse_decompress.c" #include "threading.c" #include "pool.c" -#include "xxhash.c" #include "zstd_common.c" -/* compress */ +/* lib/compress */ #include "fse_compress.c" #include "hist.c" #include "huf_compress.c" @@ -67,7 +72,7 @@ #include "zstdmt_compress.c" #endif -/* decompress */ +/* lib/decompress */ #include "huf_decompress.c" #include "zstd_ddict.c" #include "zstd_decompress.c" diff --git a/contrib/single_file_libs/zstddeclib-in.c b/contrib/single_file_libs/zstddeclib-in.c index eb88af36521..c447bc25ca3 100755 --- a/contrib/single_file_libs/zstddeclib-in.c +++ b/contrib/single_file_libs/zstddeclib-in.c @@ -1,7 +1,7 @@ /** * \file zstddeclib.c * Single-file Zstandard decompressor. - * + * * Generate using: * \code * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c @@ -18,17 +18,23 @@ */ /* * Settings to bake for the standalone decompressor. - * + * * Note: It's important that none of these affects 'zstd.h' (only the * implementation files we're amalgamating). - * + * * Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also * defined in mem.h (breaking C99 compatibility). + * + * Note: the undefs for xxHash allow Zstd's implementation to coinside with with + * standalone xxHash usage (with global defines). */ #define DEBUGLEVEL 0 #define MEM_MODULE +#undef XXH_NAMESPACE #define XXH_NAMESPACE ZSTD_ +#undef XXH_PRIVATE_API #define XXH_PRIVATE_API +#undef XXH_INLINE_ALL #define XXH_INLINE_ALL #define ZSTD_LEGACY_SUPPORT 0 #define ZSTD_LIB_COMPRESSION 0 @@ -36,15 +42,14 @@ #define ZSTD_NOBENCH #define ZSTD_STRIP_ERROR_STRINGS -/* common */ +/* lib/common */ #include "debug.c" #include "entropy_common.c" #include "error_private.c" #include "fse_decompress.c" -#include "xxhash.c" #include "zstd_common.c" -/* decompress */ +/* lib/decompress */ #include "huf_decompress.c" #include "zstd_ddict.c" #include "zstd_decompress.c" From 1658ae75cd654524df727f8cbd2d889ab42ae592 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 7 Apr 2020 14:41:53 -0700 Subject: [PATCH 275/402] handling nil case for refprefix --- lib/compress/zstd_compress.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index bb0a600729f..6a3eb5af216 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -945,9 +945,11 @@ size_t ZSTD_CCtx_refPrefix_advanced( { RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); ZSTD_clearAllDicts(cctx); - cctx->prefixDict.dict = prefix; - cctx->prefixDict.dictSize = prefixSize; - cctx->prefixDict.dictContentType = dictContentType; + if (prefix != NULL && prefixSize > 0) { + cctx->prefixDict.dict = prefix; + cctx->prefixDict.dictSize = prefixSize; + cctx->prefixDict.dictContentType = dictContentType; + } return 0; } From c22551b903d513e3094e60887861b68b52d4ed72 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Thu, 9 Apr 2020 17:13:39 -0400 Subject: [PATCH 276/402] Generate a better CMake Package Config file --- build/cmake/CMakeLists.txt | 36 +++++++++++++++++++++++++++++++++ build/cmake/lib/CMakeLists.txt | 15 -------------- build/cmake/lib/config.cmake.in | 7 ------- build/cmake/zstdConfig.cmake | 1 + 4 files changed, 37 insertions(+), 22 deletions(-) delete mode 100644 build/cmake/lib/config.cmake.in create mode 100644 build/cmake/zstdConfig.cmake diff --git a/build/cmake/CMakeLists.txt b/build/cmake/CMakeLists.txt index be5ce15186f..ac499133fda 100644 --- a/build/cmake/CMakeLists.txt +++ b/build/cmake/CMakeLists.txt @@ -158,3 +158,39 @@ add_custom_target(clean-all COMMAND ${CMAKE_BUILD_TOOL} clean COMMAND rm -rf ${CMAKE_BINARY_DIR}/ ) + +#----------------------------------------------------------------------------- +# Generate Package Config files +# +# This section is based on the boiler plate code from: +# https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-packages +#----------------------------------------------------------------------------- +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake" + VERSION ${zstd_VERSION} + COMPATIBILITY SameMajorVersion + ) + +# A Package Config file that works from the build directory +export(EXPORT zstdExports + FILE "${CMAKE_CURRENT_BINARY_DIR}/zstdTargets.cmake" + NAMESPACE zstd:: + ) +configure_file(zstdConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake" + COPYONLY + ) + +# A Package Config file that works from the installation directory +set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/zstd) +install(EXPORT zstdExports + FILE zstdTargets.cmake + NAMESPACE zstd:: + DESTINATION ${ConfigPackageLocation} + ) +install(FILES + zstdConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/zstdConfigVersion.cmake" + DESTINATION ${ConfigPackageLocation} + ) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index e92647bf186..86abf593dfa 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -169,21 +169,6 @@ if (ZSTD_BUILD_STATIC) ) endif () -# export targets + find config -configure_file( - "config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake" - @ONLY -) -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/zstdConfig.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zstd" -) -install(EXPORT zstdExports - NAMESPACE zstd:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/zstd" -) - # uninstall target if (NOT TARGET uninstall) configure_file( diff --git a/build/cmake/lib/config.cmake.in b/build/cmake/lib/config.cmake.in deleted file mode 100644 index 3a22756fcc9..00000000000 --- a/build/cmake/lib/config.cmake.in +++ /dev/null @@ -1,7 +0,0 @@ -include(FindPackageHandleStandardArgs) -set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE}) -find_package_handle_standard_args(zstd CONFIG_MODE) - -if(NOT TARGET zstd::libzstd_shared) - include("${CMAKE_CURRENT_LIST_DIR}/zstdExports.cmake") -endif() diff --git a/build/cmake/zstdConfig.cmake b/build/cmake/zstdConfig.cmake new file mode 100644 index 00000000000..ebbfcc38f6f --- /dev/null +++ b/build/cmake/zstdConfig.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/zstdTargets.cmake") From b674a1eec38dfbd5372827baf899c8c1cbead29a Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Thu, 9 Apr 2020 17:14:34 -0400 Subject: [PATCH 277/402] Fix that installation of the libzstd.pc does not respect DESTDIR installations --- build/cmake/lib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 86abf593dfa..00840a2c762 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -142,7 +142,7 @@ if (UNIX) -P "${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig.cmake" COMMENT "Creating pkg-config file") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libzstd.pc" DESTINATION "${LIBDIR}/pkgconfig") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libzstd.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif () # install target From 105d9b62ae215c30ffdd0bc11a555c064412cca1 Mon Sep 17 00:00:00 2001 From: Taylor Braun-Jones Date: Thu, 9 Apr 2020 17:15:49 -0400 Subject: [PATCH 278/402] Minor CMake refactoring/simplification --- build/cmake/lib/CMakeLists.txt | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 00840a2c762..9e758dac08c 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -77,8 +77,10 @@ if (MSVC) endif () # Split project to static and shared libraries build +set(library_targets) if (ZSTD_BUILD_SHARED) add_library(libzstd_shared SHARED ${Sources} ${Headers} ${PlatformDependResources}) + list(APPEND library_targets libzstd_shared) if (ZSTD_MULTITHREAD_SUPPORT) set_property(TARGET libzstd_shared APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD") if (UNIX) @@ -88,6 +90,7 @@ if (ZSTD_BUILD_SHARED) endif () if (ZSTD_BUILD_STATIC) add_library(libzstd_static STATIC ${Sources} ${Headers}) + list(APPEND library_targets libzstd_static) if (ZSTD_MULTITHREAD_SUPPORT) set_property(TARGET libzstd_static APPEND PROPERTY COMPILE_DEFINITIONS "ZSTD_MULTITHREAD") if (UNIX) @@ -135,7 +138,7 @@ if (UNIX) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") - set(VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") + set(VERSION "${zstd_VERSION}") add_custom_target(libzstd.pc ALL ${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc" -DPREFIX="${PREFIX}" -DVERSION="${VERSION}" @@ -154,20 +157,12 @@ install(FILES "${LIBRARY_DIR}/common/zstd_errors.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") -if (ZSTD_BUILD_SHARED) - install(TARGETS libzstd_shared EXPORT zstdExports - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" +install(TARGETS ${library_targets} + EXPORT zstdExports + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) -endif() -if (ZSTD_BUILD_STATIC) - install(TARGETS libzstd_static EXPORT zstdExports - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - ) -endif () # uninstall target if (NOT TARGET uninstall) From 458a1a1723549d76a7deec407c3575ff0bad95b0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 13 Apr 2020 10:13:29 -0700 Subject: [PATCH 279/402] minor refactor - fix a few comments - reorder some parameters, to enforce "mutable references first" - simplified fwriteSparse() --- programs/fileio.c | 120 ++++++++++++++++++++++++---------------------- tests/fullbench.c | 2 +- 2 files changed, 63 insertions(+), 59 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index f2ae1bd44bb..b00a8e60af6 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -100,7 +100,7 @@ static UTIL_time_t g_displayClock = UTIL_TIME_INITIALIZER; #define READY_FOR_UPDATE() (!g_display_prefs.noProgress && UTIL_clockSpanMicro(g_displayClock) > g_refreshRate) #define DELAY_NEXT_UPDATE() { g_displayClock = UTIL_getTime(); } #define DISPLAYUPDATE(l, ...) { \ - if (g_display_prefs.displayLevel>=l && !g_display_prefs.noProgress) { \ + if (g_display_prefs.displayLevel>=l && !g_display_prefs.noProgress) { \ if (READY_FOR_UPDATE() || (g_display_prefs.displayLevel>=4)) { \ DELAY_NEXT_UPDATE(); \ DISPLAY(__VA_ARGS__); \ @@ -1554,7 +1554,7 @@ FIO_compressFilename_srcFile(FIO_prefs_t* const prefs, int FIO_compressFilename(FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName, const char* dictFileName, - int compressionLevel, ZSTD_compressionParameters comprParams) + int compressionLevel, ZSTD_compressionParameters comprParams) { cRess_t const ress = FIO_createCResources(prefs, dictFileName, (size_t)UTIL_getFileSize(srcFileName), compressionLevel, comprParams); int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel); @@ -1717,18 +1717,19 @@ static void FIO_freeDResources(dRess_t ress) /** FIO_fwriteSparse() : -* @return : storedSkips, to be provided to next call to FIO_fwriteSparse() of LZ4IO_fwriteSparseEnd() */ +* @return : storedSkips, +* argument for next call to FIO_fwriteSparse() or FIO_fwriteSparseEnd() */ static unsigned -FIO_fwriteSparse(const FIO_prefs_t* const prefs, - FILE* file, +FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSize, + const FIO_prefs_t* const prefs, unsigned storedSkips) { const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ size_t bufferSizeT = bufferSize / sizeof(size_t); const size_t* const bufferTEnd = bufferT + bufferSizeT; const size_t* ptrT = bufferT; - static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* 0-test re-attempted every 32 KB */ + static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* check every 32 KB */ if (prefs->testMode) return 0; /* do not output anything in test mode */ @@ -1742,33 +1743,34 @@ FIO_fwriteSparse(const FIO_prefs_t* const prefs, /* avoid int overflow */ if (storedSkips > 1 GB) { - int const seekResult = LONG_SEEK(file, 1 GB, SEEK_CUR); - if (seekResult != 0) + if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0) EXM_THROW(91, "1 GB skip error (sparse file support)"); storedSkips -= 1 GB; } while (ptrT < bufferTEnd) { - size_t seg0SizeT = segmentSizeT; size_t nb0T; - /* count leading zeros */ + /* adjust last segment if < 32 KB */ + size_t seg0SizeT = segmentSizeT; if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT; bufferSizeT -= seg0SizeT; + + /* count leading zeroes */ for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ; storedSkips += (unsigned)(nb0T * sizeof(size_t)); if (nb0T != seg0SizeT) { /* not all 0s */ - int const seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR); - if (seekResult) EXM_THROW(92, "Sparse skip error ; try --no-sparse"); + size_t const nbNon0ST = seg0SizeT - nb0T; + /* skip leading zeros */ + if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0) + EXM_THROW(92, "Sparse skip error ; try --no-sparse"); storedSkips = 0; - seg0SizeT -= nb0T; - ptrT += nb0T; - { size_t const sizeCheck = fwrite(ptrT, sizeof(size_t), seg0SizeT, file); - if (sizeCheck != seg0SizeT) - EXM_THROW(93, "Write error : cannot write decoded block : %s", + /* write the rest */ + if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST) + EXM_THROW(93, "Write error : cannot write decoded block : %s", strerror(errno)); - } } + } ptrT += seg0SizeT; } @@ -1777,20 +1779,20 @@ FIO_fwriteSparse(const FIO_prefs_t* const prefs, /* size not multiple of sizeof(size_t) : implies end of block */ const char* const restStart = (const char*)bufferTEnd; const char* restPtr = restStart; - size_t restSize = bufferSize & maskT; - const char* const restEnd = restStart + restSize; + const char* const restEnd = (const char*)buffer + bufferSize; + assert(restEnd > restStart && restEnd < restStart + sizeof(size_t)); for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ; storedSkips += (unsigned) (restPtr - restStart); if (restPtr != restEnd) { - int seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR); - if (seekResult) - EXM_THROW(94, "Sparse skip error ; try --no-sparse"); + /* not all remaining bytes are 0 */ + size_t const restSize = (size_t)(restEnd - restPtr); + if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0) + EXM_THROW(92, "Sparse skip error ; try --no-sparse"); + if (fwrite(restPtr, 1, restSize, file) != restSize) + EXM_THROW(95, "Write error : cannot write end of decoded block : %s", + strerror(errno)); storedSkips = 0; - { size_t const sizeCheck = fwrite(restPtr, 1, (size_t)(restEnd - restPtr), file); - if (sizeCheck != (size_t)(restEnd - restPtr)) - EXM_THROW(95, "Write error : cannot write decoded end of block : %s", - strerror(errno)); - } } } } + } } } return storedSkips; } @@ -1833,7 +1835,7 @@ static int FIO_passThrough(const FIO_prefs_t* const prefs, do { readFromInput = fread(buffer, 1, blockSize, finput); - storedSkips = FIO_fwriteSparse(prefs, foutput, buffer, readFromInput, storedSkips); + storedSkips = FIO_fwriteSparse(foutput, buffer, readFromInput, prefs, storedSkips); } while (readFromInput == blockSize); if (ferror(finput)) { DISPLAYLEVEL(1, "Pass-through read error : %s\n", strerror(errno)); @@ -1864,34 +1866,36 @@ FIO_zstdErrorHelp(const FIO_prefs_t* const prefs, unsigned long long const windowSize = header.windowSize; unsigned const windowLog = FIO_highbit64(windowSize) + ((windowSize & (windowSize - 1)) != 0); assert(prefs->memLimit > 0); - DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u\n", + DISPLAYLEVEL(1, "%s : Window size larger than maximum : %llu > %u \n", srcFileName, windowSize, prefs->memLimit); if (windowLog <= ZSTD_WINDOWLOG_MAX) { unsigned const windowMB = (unsigned)((windowSize >> 20) + ((windowSize & ((1 MB) - 1)) != 0)); assert(windowSize < (U64)(1ULL << 52)); /* ensure now overflow for windowMB */ - DISPLAYLEVEL(1, "%s : Use --long=%u or --memory=%uMB\n", + DISPLAYLEVEL(1, "%s : Use --long=%u or --memory=%uMB \n", srcFileName, windowLog, windowMB); return; - } - } - DISPLAYLEVEL(1, "%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported\n", + } } + DISPLAYLEVEL(1, "%s : Window log larger than ZSTD_WINDOWLOG_MAX=%u; not supported \n", srcFileName, ZSTD_WINDOWLOG_MAX); } /** FIO_decompressFrame() : * @return : size of decoded zstd frame, or an error code -*/ + */ #define FIO_ERROR_FRAME_DECODING ((unsigned long long)(-2)) static unsigned long long -FIO_decompressZstdFrame(const FIO_prefs_t* const prefs, - dRess_t* ress, FILE* finput, - const char* srcFileName, U64 alreadyDecoded) +FIO_decompressZstdFrame(dRess_t* ress, FILE* finput, + const FIO_prefs_t* const prefs, + const char* srcFileName, + U64 alreadyDecoded) /* for multi-frames streams */ { U64 frameSize = 0; U32 storedSkips = 0; - size_t const srcFileLength = strlen(srcFileName); - if (srcFileLength>20) srcFileName += srcFileLength-20; /* display last 20 characters only */ + /* display last 20 characters only */ + { size_t const srcFileLength = strlen(srcFileName); + if (srcFileLength>20) srcFileName += srcFileLength-20; + } ZSTD_resetDStream(ress->dctx); @@ -1916,7 +1920,7 @@ FIO_decompressZstdFrame(const FIO_prefs_t* const prefs, } /* Write block */ - storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, outBuff.pos, storedSkips); + storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, outBuff.pos, prefs, storedSkips); frameSize += outBuff.pos; DISPLAYUPDATE(2, "\r%-20.20s : %u MB... ", srcFileName, (unsigned)((alreadyDecoded+frameSize)>>20) ); @@ -1950,8 +1954,8 @@ FIO_decompressZstdFrame(const FIO_prefs_t* const prefs, #ifdef ZSTD_GZDECOMPRESS static unsigned long long -FIO_decompressGzFrame(const FIO_prefs_t* const prefs, - dRess_t* ress, FILE* srcFile, +FIO_decompressGzFrame(dRess_t* ress, FILE* srcFile, + const FIO_prefs_t* const prefs, const char* srcFileName) { unsigned long long outFileSize = 0; @@ -1993,7 +1997,7 @@ FIO_decompressGzFrame(const FIO_prefs_t* const prefs, } { size_t const decompBytes = ress->dstBufferSize - strm.avail_out; if (decompBytes) { - storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, decompBytes, storedSkips); + storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, decompBytes, prefs, storedSkips); outFileSize += decompBytes; strm.next_out = (Bytef*)ress->dstBuffer; strm.avail_out = (uInt)ress->dstBufferSize; @@ -2018,8 +2022,8 @@ FIO_decompressGzFrame(const FIO_prefs_t* const prefs, #ifdef ZSTD_LZMADECOMPRESS static unsigned long long -FIO_decompressLzmaFrame(const FIO_prefs_t* const prefs, - dRess_t* ress, FILE* srcFile, +FIO_decompressLzmaFrame(dRess_t* ress, FILE* srcFile, + const FIO_prefs_t* const prefs, const char* srcFileName, int plain_lzma) { unsigned long long outFileSize = 0; @@ -2070,7 +2074,7 @@ FIO_decompressLzmaFrame(const FIO_prefs_t* const prefs, } { size_t const decompBytes = ress->dstBufferSize - strm.avail_out; if (decompBytes) { - storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, decompBytes, storedSkips); + storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, decompBytes, prefs, storedSkips); outFileSize += decompBytes; strm.next_out = (BYTE*)ress->dstBuffer; strm.avail_out = ress->dstBufferSize; @@ -2089,8 +2093,8 @@ FIO_decompressLzmaFrame(const FIO_prefs_t* const prefs, #ifdef ZSTD_LZ4DECOMPRESS static unsigned long long -FIO_decompressLz4Frame(const FIO_prefs_t* const prefs, - dRess_t* ress, FILE* srcFile, +FIO_decompressLz4Frame(dRess_t* ress, FILE* srcFile, + const FIO_prefs_t* const prefs, const char* srcFileName) { unsigned long long filesize = 0; @@ -2142,7 +2146,7 @@ FIO_decompressLz4Frame(const FIO_prefs_t* const prefs, /* Write Block */ if (decodedBytes) { - storedSkips = FIO_fwriteSparse(prefs, ress->dstFile, ress->dstBuffer, decodedBytes, storedSkips); + storedSkips = FIO_fwriteSparse(ress->dstFile, ress->dstBuffer, decodedBytes, prefs, storedSkips); filesize += decodedBytes; DISPLAYUPDATE(2, "\rDecompressed : %u MB ", (unsigned)(filesize>>20)); } @@ -2177,8 +2181,8 @@ FIO_decompressLz4Frame(const FIO_prefs_t* const prefs, * @return : 0 : OK * 1 : error */ -static int FIO_decompressFrames(const FIO_prefs_t* const prefs, - dRess_t ress, FILE* srcFile, +static int FIO_decompressFrames(dRess_t ress, FILE* srcFile, + const FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName) { unsigned readSomething = 0; @@ -2206,12 +2210,12 @@ static int FIO_decompressFrames(const FIO_prefs_t* const prefs, return 1; } if (ZSTD_isFrame(buf, ress.srcBufferLoaded)) { - unsigned long long const frameSize = FIO_decompressZstdFrame(prefs, &ress, srcFile, srcFileName, filesize); + unsigned long long const frameSize = FIO_decompressZstdFrame(&ress, srcFile, prefs, srcFileName, filesize); if (frameSize == FIO_ERROR_FRAME_DECODING) return 1; filesize += frameSize; } else if (buf[0] == 31 && buf[1] == 139) { /* gz magic number */ #ifdef ZSTD_GZDECOMPRESS - unsigned long long const frameSize = FIO_decompressGzFrame(prefs, &ress, srcFile, srcFileName); + unsigned long long const frameSize = FIO_decompressGzFrame(&ress, srcFile, prefs, srcFileName); if (frameSize == FIO_ERROR_FRAME_DECODING) return 1; filesize += frameSize; #else @@ -2221,7 +2225,7 @@ static int FIO_decompressFrames(const FIO_prefs_t* const prefs, } else if ((buf[0] == 0xFD && buf[1] == 0x37) /* xz magic number */ || (buf[0] == 0x5D && buf[1] == 0x00)) { /* lzma header (no magic number) */ #ifdef ZSTD_LZMADECOMPRESS - unsigned long long const frameSize = FIO_decompressLzmaFrame(prefs, &ress, srcFile, srcFileName, buf[0] != 0xFD); + unsigned long long const frameSize = FIO_decompressLzmaFrame(&ress, srcFile, prefs, srcFileName, buf[0] != 0xFD); if (frameSize == FIO_ERROR_FRAME_DECODING) return 1; filesize += frameSize; #else @@ -2230,7 +2234,7 @@ static int FIO_decompressFrames(const FIO_prefs_t* const prefs, #endif } else if (MEM_readLE32(buf) == LZ4_MAGICNUMBER) { #ifdef ZSTD_LZ4DECOMPRESS - unsigned long long const frameSize = FIO_decompressLz4Frame(prefs, &ress, srcFile, srcFileName); + unsigned long long const frameSize = FIO_decompressLz4Frame(&ress, srcFile, prefs, srcFileName); if (frameSize == FIO_ERROR_FRAME_DECODING) return 1; filesize += frameSize; #else @@ -2287,7 +2291,7 @@ static int FIO_decompressDstFile(FIO_prefs_t* const prefs, transfer_permissions = 1; } - result = FIO_decompressFrames(prefs, ress, srcFile, dstFileName, srcFileName); + result = FIO_decompressFrames(ress, srcFile, prefs, dstFileName, srcFileName); if (releaseDstFile) { FILE* const dstFile = ress.dstFile; @@ -2768,7 +2772,7 @@ FIO_listFile(fileInfo_t* total, const char* inFileName, int displayLevel) displayInfo(inFileName, &info, displayLevel); *total = FIO_addFInfo(*total, info); assert(error == info_success || error == info_frame_error); - return error; + return (int)error; } } diff --git a/tests/fullbench.c b/tests/fullbench.c index 5eccfc5594b..f0179a9d1fe 100644 --- a/tests/fullbench.c +++ b/tests/fullbench.c @@ -20,7 +20,7 @@ #include "timefn.h" /* UTIL_clockSpanNano, UTIL_getTime */ #include "mem.h" /* U32 */ #ifndef ZSTD_DLL_IMPORT - #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, blockType_e, KB, MB */ + #include "zstd_internal.h" /* ZSTD_decodeSeqHeaders, ZSTD_blockHeaderSize, ZSTD_getcBlockSize, blockType_e, KB, MB */ #else #define KB *(1 <<10) #define MB *(1 <<20) From 5b0a452cac9672a3003781541235dc47727e6c2a Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 17 Apr 2020 15:58:53 -0500 Subject: [PATCH 280/402] Adding --long support for --patch-from (#1959) * adding long support for patch-from * adding refPrefix to dictionary_decompress * adding refPrefix to dictionary_loader * conversion nit * triggering log mode on chainLog < fileLog and removing old threshold * adding refPrefix to dictionary_round_trip * adding docs * adding enableldm + forceWindow test for dict * separate patch-from logic into FIO_adjustParamsForPatchFromMode * moving memLimit adjustment to outside ifdefs (need for decomp) * removing refPrefix gate on dictionary_round_trip * rebase on top of dev refPrefix change * making sure refPrefx + ldm is < 1% of srcSize * combining notes for patch-from * moving memlimit logic inside fileio.c * adding display for optimal parser and long mode trigger * conversion nit * fuzzer found heap-overflow fix * another conversion nit * moving FIO_adjustMemLimitForPatchFromMode outside ifndef * making params immutable * moving memLimit update before createDictBuffer call * making maxSrcSize unsigned long long * making dictSize and maxSrcSize params unsigned long long * error on files larger than 4gb * extend refPrefix test to include round trip * conversion to size_t * making sure ldm is at least 10x better * removing break * including zstd_compress_internal and removing redundant macros * exposing ZSTD_cycleLog() * using cycleLog instead of chainLog * add some more docs about user optimizations * formatting --- lib/compress/zstd_compress.c | 24 ++-- lib/compress/zstd_compress_internal.h | 4 + lib/compress/zstd_ldm.c | 14 ++- lib/compress/zstd_ldm.h | 4 + lib/compress/zstdmt_compress.c | 15 ++- programs/fileio.c | 171 ++++++++++++++++---------- programs/zstd.1.md | 8 ++ programs/zstdcli.c | 10 +- tests/fuzz/dictionary_decompress.c | 7 +- tests/fuzz/dictionary_loader.c | 23 +++- tests/fuzzer.c | 121 +++++++++++++++++- tests/playTests.sh | 13 +- 12 files changed, 318 insertions(+), 96 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 40fdecae75f..d458b84461c 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1011,7 +1011,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams) /** ZSTD_cycleLog() : * condition for correct operation : hashLog > 1 */ -static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) +U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) { U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); return hashLog - btScale; @@ -2784,6 +2784,7 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const * @return : 0, or an error code */ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, + ldmState_t* ls, ZSTD_cwksp* ws, ZSTD_CCtx_params const* params, const void* src, size_t srcSize, @@ -2795,6 +2796,11 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_window_update(&ms->window, src, srcSize); ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); + if (params->ldmParams.enableLdm && ls != NULL) { + ZSTD_window_update(&ls->window, src, srcSize); + ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); + } + /* Assert that we the ms params match the params we're being given */ ZSTD_assertEqualCParams(params->cParams, ms->cParams); @@ -2807,6 +2813,9 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk); + if (params->ldmParams.enableLdm && ls != NULL && srcSize >= params->ldmParams.minMatchLength) + ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams); + switch(params->cParams.strategy) { case ZSTD_fast: @@ -2985,7 +2994,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( - ms, ws, params, dictPtr, dictContentSize, dtlm)); + ms, NULL, ws, params, dictPtr, dictContentSize, dtlm)); return dictID; } } @@ -2995,6 +3004,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, static size_t ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, ZSTD_matchState_t* ms, + ldmState_t* ls, ZSTD_cwksp* ws, const ZSTD_CCtx_params* params, const void* dict, size_t dictSize, @@ -3012,13 +3022,13 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, /* dict restricted modes */ if (dictContentType == ZSTD_dct_rawContent) - return ZSTD_loadDictionaryContent(ms, ws, params, dict, dictSize, dtlm); + return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm); if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) { if (dictContentType == ZSTD_dct_auto) { DEBUGLOG(4, "raw content dictionary detected"); return ZSTD_loadDictionaryContent( - ms, ws, params, dict, dictSize, dtlm); + ms, ls, ws, params, dict, dictSize, dtlm); } RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong); assert(0); /* impossible */ @@ -3061,12 +3071,12 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, { size_t const dictID = cdict ? ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->workspace, &cctx->appliedParams, cdict->dictContent, + &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, cdict->dictContentSize, dictContentType, dtlm, cctx->entropyWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->workspace, &cctx->appliedParams, dict, dictSize, + &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); FORWARD_IF_ERROR(dictID); assert(dictID <= UINT_MAX); @@ -3344,7 +3354,7 @@ static size_t ZSTD_initCDict_internal( params.fParams.contentSizeFlag = 1; params.cParams = cParams; { size_t const dictID = ZSTD_compress_insertDictionary( - &cdict->cBlockState, &cdict->matchState, &cdict->workspace, + &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, ¶ms, cdict->dictContent, cdict->dictContentSize, dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace); FORWARD_IF_ERROR(dictID); diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 95e1a52edd0..893e8def209 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -166,6 +166,7 @@ typedef struct { typedef struct { ZSTD_window_t window; /* State for the window round buffer management */ ldmEntry_t* hashTable; + U32 loadedDictEnd; BYTE* bucketOffsets; /* Next position in bucket to insert entry */ U64 hashPower; /* Used to compute the rolling hash. * Depends on ldmParams.minMatchLength */ @@ -1051,5 +1052,8 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity); */ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq); +/** ZSTD_cycleLog() : + * condition for correct operation : hashLog > 1 */ +U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat); #endif /* ZSTD_COMPRESS_H */ diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index d9dd5a95f7e..0e72c0b5986 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -224,6 +224,17 @@ static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state, return rollingHash; } +void ZSTD_ldm_fillHashTable( + ldmState_t* state, const BYTE* ip, + const BYTE* iend, ldmParams_t const* params) +{ + U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength); + ZSTD_ldm_fillLdmHashTable( + state, startingHash, ip, iend - params->minMatchLength, state->window.base, + params->hashLog - params->bucketSizeLog, + *params); +} + /** ZSTD_ldm_limitTableUpdate() : * @@ -459,7 +470,7 @@ size_t ZSTD_ldm_generateSequences( * * Try invalidation after the sequence generation and test the * the offset against maxDist directly. */ - ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, NULL, NULL); + ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, &ldmState->loadedDictEnd, NULL); /* 3. Generate the sequences for the chunk, and get newLeftoverSize. */ newLeftoverSize = ZSTD_ldm_generateSequences_internal( ldmState, sequences, params, chunkStart, chunkSize); @@ -567,7 +578,6 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, if (sequence.offset == 0) break; - assert(sequence.offset <= (1U << cParams->windowLog)); assert(ip + sequence.litLength + sequence.matchLength <= iend); /* Fill tables for block compressor */ diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index 7e3326c8c9d..aa2b6c52ec8 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -24,6 +24,10 @@ extern "C" { #define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT +void ZSTD_ldm_fillHashTable( + ldmState_t* state, const BYTE* ip, + const BYTE* iend, ldmParams_t const* params); + /** * ZSTD_ldm_generateSequences(): * diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index fd6d9895946..12ebcd2b5bc 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -461,7 +461,9 @@ typedef struct { ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */ } serialState_t; -static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, size_t jobSize) +static int ZSTDMT_serialState_reset(serialState_t* serialState, + ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, + size_t jobSize, const void* dict, size_t const dictSize) { /* Adjust parameters */ if (params.ldmParams.enableLdm) { @@ -507,6 +509,13 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* memset(serialState->ldmState.hashTable, 0, hashSize); memset(serialState->ldmState.bucketOffsets, 0, bucketSize); } + + /* Update window state and fill hash table with dict */ + if (params.ldmParams.enableLdm && dict) { + ZSTD_window_update(&serialState->ldmState.window, dict, dictSize); + ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, (const BYTE*)dict + dictSize, ¶ms.ldmParams); + } + serialState->params = params; serialState->params.jobSize = (U32)jobSize; return 0; @@ -1267,7 +1276,7 @@ static size_t ZSTDMT_compress_advanced_internal( assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */ ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) ); - if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize)) + if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0)) return ERROR(memory_allocation); FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */ @@ -1500,7 +1509,7 @@ size_t ZSTDMT_initCStream_internal( mtctx->allJobsCompleted = 0; mtctx->consumed = 0; mtctx->produced = 0; - if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize)) + if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize, dict, dictSize)) return ERROR(memory_allocation); return 0; } diff --git a/programs/fileio.c b/programs/fileio.c index b00a8e60af6..d450f5c9833 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -45,6 +45,7 @@ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */ #include "zstd.h" #include "zstd_errors.h" /* ZSTD_error_frameParameter_windowTooLarge */ +#include "zstd_compress_internal.h" #if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS) # include @@ -68,17 +69,11 @@ /*-************************************* * Constants ***************************************/ -#define KB *(1<<10) -#define MB *(1<<20) -#define GB *(1U<<30) - #define ADAPT_WINDOWLOG_DEFAULT 23 /* 8 MB */ #define DICTSIZE_MAX (32 MB) /* protection against large input (attack scenario) */ #define FNSPACE 30 -#define PATCHFROM_WINDOWSIZE_EXTRA_BYTES 1 KB - /*-************************************* * Macros ***************************************/ @@ -771,6 +766,16 @@ static unsigned FIO_highbit64(unsigned long long v) return count; } +static void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs, + unsigned long long const dictSize, + unsigned long long const maxSrcFileSize) +{ + unsigned long long maxSize = MAX(prefs->memLimit, MAX(dictSize, maxSrcFileSize)); + assert(maxSize != UTIL_FILESIZE_UNKNOWN); + if (maxSize > UINT_MAX) + EXM_THROW(42, "Can't handle files larger than %u GB\n", UINT_MAX/(1 GB) + 1); + FIO_setMemLimit(prefs, (unsigned)maxSize); +} #ifndef ZSTD_NOCOMPRESS @@ -784,12 +789,40 @@ typedef struct { size_t srcBufferSize; void* dstBuffer; size_t dstBufferSize; + void* dictBuffer; + size_t dictBufferSize; const char* dictFileName; ZSTD_CStream* cctx; } cRess_t; +static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, + ZSTD_compressionParameters* comprParams, + unsigned long long const dictSize, + unsigned long long const maxSrcFileSize, + int cLevel) +{ + unsigned const fileWindowLog = FIO_highbit64(maxSrcFileSize) + 1; + ZSTD_compressionParameters const cParams = ZSTD_getCParams(cLevel, (size_t)maxSrcFileSize, (size_t)dictSize); + FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, maxSrcFileSize); + if (fileWindowLog > ZSTD_WINDOWLOG_MAX) + DISPLAYLEVEL(1, "Max window log exceeded by file (compression ratio will suffer)\n"); + comprParams->windowLog = MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog); + if (fileWindowLog > ZSTD_cycleLog(comprParams->hashLog, cParams.strategy)) { + if (!prefs->ldmFlag) + DISPLAYLEVEL(1, "long mode automaticaly triggered\n"); + FIO_setLdmFlag(prefs, 1); + } + if (cParams.strategy >= ZSTD_btopt) { + DISPLAYLEVEL(1, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n"); + DISPLAYLEVEL(1, "- Use --single-thread mode in the zstd cli"); + DISPLAYLEVEL(1, "- Set a larger targetLength (eg. --zstd=targetLength=4096)\n"); + DISPLAYLEVEL(1, "- Set a larger chainLog (eg. --zstd=chainLog=31)\n"); + DISPLAYLEVEL(1, "Also consdier playing around with searchLog and hashLog\n"); + } +} + static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, - const char* dictFileName, const size_t maxSrcFileSize, + const char* dictFileName, unsigned long long const maxSrcFileSize, int cLevel, ZSTD_compressionParameters comprParams) { cRess_t ress; memset(&ress, 0, sizeof(ress)); @@ -802,69 +835,70 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, ress.srcBufferSize = ZSTD_CStreamInSize(); ress.srcBuffer = malloc(ress.srcBufferSize); ress.dstBufferSize = ZSTD_CStreamOutSize(); + + /* need to update memLimit before calling createDictBuffer + * because of memLimit check inside it */ + if (prefs->patchFromMode) + FIO_adjustParamsForPatchFromMode(prefs, &comprParams, UTIL_getFileSize(dictFileName), maxSrcFileSize, cLevel); ress.dstBuffer = malloc(ress.dstBufferSize); + ress.dictBufferSize = FIO_createDictBuffer(&ress.dictBuffer, dictFileName, prefs); /* works with dictFileName==NULL */ if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "allocation error : not enough memory"); /* Advanced parameters, including dictionary */ - { void* dictBuffer; - size_t const dictBuffSize = FIO_createDictBuffer(&dictBuffer, dictFileName, prefs); /* works with dictFileName==NULL */ - if (dictFileName && (dictBuffer==NULL)) - EXM_THROW(32, "allocation error : can't create dictBuffer"); - ress.dictFileName = dictFileName; - - if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog) - comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT; - - if (prefs->patchFromMode) { - comprParams.windowLog = FIO_highbit64((unsigned long long)maxSrcFileSize + PATCHFROM_WINDOWSIZE_EXTRA_BYTES); - } - - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, 1) ); /* always enable content size when available (note: supposed to be default) */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, prefs->contentSize) ); - /* compression level */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) ); - /* max compressed block size */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) ); - /* source size hint */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_srcSizeHint, (int)prefs->srcSizeHint) ); - /* long distance matching */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) ); - if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) { - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) ); - } - if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) { - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) ); - } - /* compression parameters */ - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, comprParams.strategy) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) ); - /* multi-threading */ + if (dictFileName && (ress.dictBuffer==NULL)) + EXM_THROW(32, "allocation error : can't create dictBuffer"); + ress.dictFileName = dictFileName; + + if (prefs->adaptiveMode && !prefs->ldmFlag && !comprParams.windowLog) + comprParams.windowLog = ADAPT_WINDOWLOG_DEFAULT; + + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_contentSizeFlag, prefs->contentSize) ); /* always enable content size when available (note: supposed to be default) */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_dictIDFlag, prefs->dictIDFlag) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_checksumFlag, prefs->checksumFlag) ); + /* compression level */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_compressionLevel, cLevel) ); + /* max compressed block size */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetCBlockSize, (int)prefs->targetCBlockSize) ); + /* source size hint */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_srcSizeHint, (int)prefs->srcSizeHint) ); + /* long distance matching */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_enableLongDistanceMatching, prefs->ldmFlag) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashLog, prefs->ldmHashLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmMinMatch, prefs->ldmMinMatch) ); + if (prefs->ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET) { + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmBucketSizeLog, prefs->ldmBucketSizeLog) ); + } + if (prefs->ldmHashRateLog != FIO_LDM_PARAM_NOTSET) { + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_ldmHashRateLog, prefs->ldmHashRateLog) ); + } + /* compression parameters */ + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_windowLog, (int)comprParams.windowLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_chainLog, (int)comprParams.chainLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_hashLog, (int)comprParams.hashLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_searchLog, (int)comprParams.searchLog) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_minMatch, (int)comprParams.minMatch) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_targetLength, (int)comprParams.targetLength) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_strategy, comprParams.strategy) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_literalCompressionMode, (int)prefs->literalCompressionMode) ); + /* multi-threading */ #ifdef ZSTD_MULTITHREAD - DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) ); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->blockSize) ); - if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) { - DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog); - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) ); - } - CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) ); + DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_nbWorkers, prefs->nbWorkers) ); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_jobSize, prefs->blockSize) ); + if (prefs->overlapLog != FIO_OVERLAP_LOG_NOTSET) { + DISPLAYLEVEL(3,"set overlapLog = %u \n", prefs->overlapLog); + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_overlapLog, prefs->overlapLog) ); + } + CHECK( ZSTD_CCtx_setParameter(ress.cctx, ZSTD_c_rsyncable, prefs->rsyncable) ); #endif - /* dictionary */ - CHECK( ZSTD_CCtx_loadDictionary(ress.cctx, dictBuffer, dictBuffSize) ); - free(dictBuffer); + /* dictionary */ + if (prefs->patchFromMode) { + CHECK( ZSTD_CCtx_refPrefix(ress.cctx, ress.dictBuffer, ress.dictBufferSize) ); + } else { + CHECK( ZSTD_CCtx_loadDictionary(ress.cctx, ress.dictBuffer, ress.dictBufferSize) ); } - + return ress; } @@ -872,6 +906,7 @@ static void FIO_freeCResources(cRess_t ress) { free(ress.srcBuffer); free(ress.dstBuffer); + free(ress.dictBuffer); ZSTD_freeCStream(ress.cctx); /* never fails */ } @@ -1556,7 +1591,7 @@ int FIO_compressFilename(FIO_prefs_t* const prefs, const char* dstFileName, const char* srcFileName, const char* dictFileName, int compressionLevel, ZSTD_compressionParameters comprParams) { - cRess_t const ress = FIO_createCResources(prefs, dictFileName, (size_t)UTIL_getFileSize(srcFileName), compressionLevel, comprParams); + cRess_t const ress = FIO_createCResources(prefs, dictFileName, UTIL_getFileSize(srcFileName), compressionLevel, comprParams); int const result = FIO_compressFilename_srcFile(prefs, ress, dstFileName, srcFileName, compressionLevel); @@ -1604,11 +1639,12 @@ FIO_determineCompressedName(const char* srcFileName, const char* outDirName, con return dstFileNameBuffer; } -static size_t FIO_getLargestFileSize(const char** inFileNames, unsigned nbFiles) +static unsigned long long FIO_getLargestFileSize(const char** inFileNames, unsigned nbFiles) { - size_t i, fileSize, maxFileSize = 0; + size_t i; + unsigned long long fileSize, maxFileSize = 0; for (i = 0; i < nbFiles; i++) { - fileSize = (size_t)UTIL_getFileSize(inFileNames[i]); + fileSize = UTIL_getFileSize(inFileNames[i]); maxFileSize = fileSize > maxFileSize ? fileSize : maxFileSize; } return maxFileSize; @@ -1686,6 +1722,9 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi dRess_t ress; memset(&ress, 0, sizeof(ress)); + if (prefs->patchFromMode) + FIO_adjustMemLimitForPatchFromMode(prefs, UTIL_getFileSize(dictFileName), 0 /* just use the dict size */); + /* Allocation */ ress.dctx = ZSTD_createDStream(); if (ress.dctx==NULL) diff --git a/programs/zstd.1.md b/programs/zstd.1.md index bb8b706b733..550e2e53fe5 100644 --- a/programs/zstd.1.md +++ b/programs/zstd.1.md @@ -128,6 +128,14 @@ the last one takes effect. selection, namely that windowSize > srcSize. Note: cannot use both this and -D together + Note: `--long` mode will be automatically activated if chainLog < fileLog + (fileLog being the windowLog requried to cover the whole file). You + can also manually force it. + Node: for all levels, you can use --patch-from in --single-thread mode + to improve compression ratio at the cost of speed + Note: for level 19, you can get increased compression ratio at the cost + of speed by specifying `--zstd=targetLength=` to be something large + (i.e 4096), and by setting a large `--zstd=chainLog=` * `-M#`, `--memory=#`: Set a memory usage limit. By default, Zstandard uses 128 MB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 5eb561c1858..3e293c57b7b 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1240,6 +1240,11 @@ int main(int const argCount, const char* argv[]) CLEAN_RETURN(1); } + if (patchFromDictFileName != NULL && filenames->tableSize > 1) { + DISPLAY("error : can't use --patch-from=# on multiple files \n"); + CLEAN_RETURN(1); + } + /* No status message in pipe mode (stdin - stdout) or multi-files mode */ if (!strcmp(filenames->fileNames[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (g_displayLevel==2)) g_displayLevel=1; if ((filenames->tableSize > 1) & (g_displayLevel==2)) g_displayLevel=1; @@ -1247,15 +1252,14 @@ int main(int const argCount, const char* argv[]) /* IO Stream/File */ FIO_setNotificationLevel(g_displayLevel); FIO_setPatchFromMode(prefs, patchFromDictFileName != NULL); - if (patchFromDictFileName != NULL) { - dictFileName = patchFromDictFileName; - } if (memLimit == 0) { if (compressionParams.windowLog == 0) { memLimit = (U32)1 << g_defaultMaxWindowLog; } else { memLimit = (U32)1 << (compressionParams.windowLog & 31); } } + if (patchFromDictFileName != NULL) + dictFileName = patchFromDictFileName; FIO_setMemLimit(prefs, memLimit); if (operation==zom_compress) { #ifndef ZSTD_NOCOMPRESS diff --git a/tests/fuzz/dictionary_decompress.c b/tests/fuzz/dictionary_decompress.c index 139c90af3a2..55d2a57f18f 100644 --- a/tests/fuzz/dictionary_decompress.c +++ b/tests/fuzz/dictionary_decompress.c @@ -42,10 +42,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) ddict = ZSTD_createDDict(dict.buff, dict.size); FUZZ_ASSERT(ddict); } else { - FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( + if (FUZZ_dataProducer_uint32Range(producer, 0, 1) == 0) + FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( dctx, dict.buff, dict.size, (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), (ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2))); + else + FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced( + dctx, dict.buff, dict.size, + (ZSTD_dictContentType_e)FUZZ_dataProducer_uint32Range(producer, 0, 2))); } { diff --git a/tests/fuzz/dictionary_loader.c b/tests/fuzz/dictionary_loader.c index 014d6b85962..5a211c5de4b 100644 --- a/tests/fuzz/dictionary_loader.c +++ b/tests/fuzz/dictionary_loader.c @@ -28,10 +28,15 @@ static size_t compress(void* compressed, size_t compressedCapacity, void const* source, size_t sourceSize, void const* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType) + ZSTD_dictContentType_e dictContentType, + int const refPrefix) { ZSTD_CCtx* cctx = ZSTD_createCCtx(); - FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( + if (refPrefix) + FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced( + cctx, dict, dictSize, dictContentType)); + else + FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( cctx, dict, dictSize, dictLoadMethod, dictContentType)); size_t const compressedSize = ZSTD_compress2( cctx, compressed, compressedCapacity, source, sourceSize); @@ -43,10 +48,15 @@ static size_t decompress(void* result, size_t resultCapacity, void const* compressed, size_t compressedSize, void const* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType) + ZSTD_dictContentType_e dictContentType, + int const refPrefix) { ZSTD_DCtx* dctx = ZSTD_createDCtx(); - FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( + if (refPrefix) + FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced( + dctx, dict, dictSize, dictContentType)); + else + FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( dctx, dict, dictSize, dictLoadMethod, dictContentType)); size_t const resultSize = ZSTD_decompressDCtx( dctx, result, resultCapacity, compressed, compressedSize); @@ -58,6 +68,7 @@ static size_t decompress(void* result, size_t resultCapacity, int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); + int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0; ZSTD_dictLoadMethod_e const dlm = size = FUZZ_dataProducer_uint32Range(producer, 0, 1); ZSTD_dictContentType_e const dct = @@ -75,14 +86,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_ASSERT(cBuf); size_t const cSize = - compress(cBuf, cBufSize, src, size, src, size, dlm, dct); + compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix); /* compression failing is okay */ if (ZSTD_isError(cSize)) { FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, "Raw must always succeed!"); goto out; } size_t const rSize = - decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct); + decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix); FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size"); FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index c102046c30f..c62fd2f9d81 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -536,15 +536,15 @@ static int basicUnitTests(U32 const seed, double compressibility) BYTE* const dst = (BYTE*)compressedBuffer; ZSTD_DCtx* dctx = ZSTD_createDCtx(); - + /* create a large frame and then a bunch of small frames */ - size_t srcSize = ZSTD_compress((void*)dst, + size_t srcSize = ZSTD_compress((void*)dst, compressedBufferSize, CNBuffer, largeFrameSrcSize, 3); - for (i = 0; i < nbFrames; i++) - srcSize += ZSTD_compress((void*)(dst + srcSize), - compressedBufferSize - srcSize, CNBuffer, + for (i = 0; i < nbFrames; i++) + srcSize += ZSTD_compress((void*)(dst + srcSize), + compressedBufferSize - srcSize, CNBuffer, smallFrameSrcSize, 3); - + /* decompressStream and make sure that dctx size was reduced at least once */ while (consumed < srcSize) { ZSTD_inBuffer in = {(void*)(dst + consumed), MIN(1, srcSize - consumed), 0}; @@ -566,6 +566,115 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ldm fill dict out-of-bounds check", testNb++); + { + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + + size_t const size = (1U << 10); + size_t const dstCapacity = ZSTD_compressBound(size); + void* dict = (void*)malloc(size); + void* src = (void*)malloc(size); + void* dst = (void*)malloc(dstCapacity); + + RDG_genBuffer(dict, size, 0.5, 0.5, seed); + RDG_genBuffer(src, size, 0.5, 0.5, seed); + + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1)); + assert(!ZSTD_isError(ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, size, dict, size, 3))); + + ZSTD_freeCCtx(cctx); + free(dict); + free(src); + free(dst); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : testing dict compression with enableLdm and forceMaxWindow : ", testNb++); + { + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + void* dict = (void*)malloc(CNBuffSize); + + RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed); + RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed); + + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1)); + assert(!ZSTD_isError(ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize, + CNBuffer, CNBuffSize, dict, CNBuffSize, 3))); + + ZSTD_freeCCtx(cctx); + free(dict); + } + DISPLAYLEVEL(3, "OK \n"); + + /* Note: this test takes 0.5 seconds to run */ + DISPLAYLEVEL(3, "test%3i : testing refPrefx vs refPrefx + ldm (size comparison) : ", testNb++); + { + /* test a big buffer so that ldm can take effect */ + size_t const size = 100 MB; + int const windowLog = 27; + size_t const dstSize = ZSTD_compressBound(size); + + void* dict = (void*)malloc(size); + void* src = (void*)malloc(size); + void* dst = (void*)malloc(dstSize); + void* recon = (void*)malloc(size); + + size_t refPrefixCompressedSize = 0; + size_t refPrefixLdmComrpessedSize = 0; + size_t reconSize = 0; + + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + + /* make dict and src the same uncompressible data */ + RDG_genBuffer(src, size, 0, 0, seed); + memcpy(dict, src, size); + assert(!memcmp(dict, src, size)); + + /* set level 1 and windowLog to cover src */ + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 1)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, windowLog)); + + /* compress on level 1 using just refPrefix and no ldm */ + ZSTD_CCtx_refPrefix(cctx, dict, size); + refPrefixCompressedSize = ZSTD_compress2(cctx, dst, dstSize, src, size); + assert(!ZSTD_isError(refPrefixCompressedSize)); + + /* test round trip just refPrefix */ + ZSTD_DCtx_refPrefix(dctx, dict, size); + reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixCompressedSize); + assert(!ZSTD_isError(reconSize)); + assert(reconSize == size); + assert(!memcmp(recon, src, size)); + + /* compress on level 1 using refPrefix and ldm */ + ZSTD_CCtx_refPrefix(cctx, dict, size);; + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1)) + refPrefixLdmComrpessedSize = ZSTD_compress2(cctx, dst, dstSize, src, size); + assert(!ZSTD_isError(refPrefixLdmComrpessedSize)); + + /* test round trip refPrefix + ldm*/ + ZSTD_DCtx_refPrefix(dctx, dict, size); + reconSize = ZSTD_decompressDCtx(dctx, recon, size, dst, refPrefixLdmComrpessedSize); + assert(!ZSTD_isError(reconSize)); + assert(reconSize == size); + assert(!memcmp(recon, src, size)); + + /* make sure that refPrefixCompressedSize is significantly greater */ + assert(refPrefixCompressedSize > 10 * refPrefixLdmComrpessedSize); + /* make sure the ldm comrpessed size is less than 1% of original */ + assert((double)refPrefixLdmComrpessedSize / (double)size < 0.01); + + ZSTD_freeDCtx(dctx); + ZSTD_freeCCtx(cctx); + free(recon); + free(dict); + free(src); + free(dst); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3d: superblock uncompressible data, too many nocompress superblocks : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); diff --git a/tests/playTests.sh b/tests/playTests.sh index 7a21376bd29..db82c9a0c9f 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1262,11 +1262,20 @@ println "\n===> patch-from tests" datagen -g1000 -P50 > tmp_dict datagen -g1000 -P10 > tmp_patch -zstd --memory=10000 --patch-from=tmp_dict tmp_patch -o tmp_patch_diff -zstd -d --memory=10000 --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon +zstd --patch-from=tmp_dict tmp_patch -o tmp_patch_diff +zstd -d --patch-from=tmp_dict tmp_patch_diff -o tmp_patch_recon $DIFF -s tmp_patch_recon tmp_patch rm -rf tmp_* +println "\n===> patch-from recursive tests" + +mkdir tmp_dir +datagen > tmp_dir/tmp1 +datagen > tmp_dir/tmp2 +datagen > tmp_dict +zstd --patch-from=tmp_dict -r tmp_dir && die +rm -rf tmp* + println "\n===> large files tests " roundTripTest -g270000000 1 From 587a20a12af1fbc96480764eef379bffd3ece6c7 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 20 Apr 2020 10:25:58 -0700 Subject: [PATCH 281/402] adding newline --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index d450f5c9833..62f31f300b6 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -814,7 +814,7 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, } if (cParams.strategy >= ZSTD_btopt) { DISPLAYLEVEL(1, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n"); - DISPLAYLEVEL(1, "- Use --single-thread mode in the zstd cli"); + DISPLAYLEVEL(1, "- Use --single-thread mode in the zstd cli\n"); DISPLAYLEVEL(1, "- Set a larger targetLength (eg. --zstd=targetLength=4096)\n"); DISPLAYLEVEL(1, "- Set a larger chainLog (eg. --zstd=chainLog=31)\n"); DISPLAYLEVEL(1, "Also consdier playing around with searchLog and hashLog\n"); From b640802ff885aa38563a7b293142e07111f1fa60 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 20 Apr 2020 11:34:24 -0700 Subject: [PATCH 282/402] updating chainlog bound --- programs/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/fileio.c b/programs/fileio.c index 62f31f300b6..98a25d94d0e 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -816,7 +816,7 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, DISPLAYLEVEL(1, "[Optimal parser notes] Consider the following to improve patch size at the cost of speed:\n"); DISPLAYLEVEL(1, "- Use --single-thread mode in the zstd cli\n"); DISPLAYLEVEL(1, "- Set a larger targetLength (eg. --zstd=targetLength=4096)\n"); - DISPLAYLEVEL(1, "- Set a larger chainLog (eg. --zstd=chainLog=31)\n"); + DISPLAYLEVEL(1, "- Set a larger chainLog (eg. --zstd=chainLog=%u)\n", ZSTD_CHAINLOG_MAX); DISPLAYLEVEL(1, "Also consdier playing around with searchLog and hashLog\n"); } } From 0b107188b869e59a995dd4637aedaea5d07514e1 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 21 Apr 2020 21:04:55 -0500 Subject: [PATCH 283/402] adding test for long mode trigger --- tests/playTests.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index db82c9a0c9f..0276f58e1fe 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1270,11 +1270,19 @@ rm -rf tmp_* println "\n===> patch-from recursive tests" mkdir tmp_dir -datagen > tmp_dir/tmp1 +datagen > tmp_dir/tmp1 datagen > tmp_dir/tmp2 datagen > tmp_dict zstd --patch-from=tmp_dict -r tmp_dir && die -rm -rf tmp* +rm -rf tmp* + +println "\n===> patch-from long mode trigger larger file test" + +datagen -g5000000 > tmp_dict +datagen -g5000000 > tmp_patch +zstd -15 --patch-from=tmp_dict tmp_patch &> tmp_out +grep "long mode automaticaly triggered" tmp_out +rm -rf tmp* println "\n===> large files tests " From 659ff85cf5e296f31c09ac21f51068d78472fd09 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 21 Apr 2020 21:12:50 -0500 Subject: [PATCH 284/402] changing to cParams.hashLog --- programs/fileio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/programs/fileio.c b/programs/fileio.c index 98a25d94d0e..802e6fb61c7 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -767,7 +767,7 @@ static unsigned FIO_highbit64(unsigned long long v) } static void FIO_adjustMemLimitForPatchFromMode(FIO_prefs_t* const prefs, - unsigned long long const dictSize, + unsigned long long const dictSize, unsigned long long const maxSrcFileSize) { unsigned long long maxSize = MAX(prefs->memLimit, MAX(dictSize, maxSrcFileSize)); @@ -795,9 +795,9 @@ typedef struct { ZSTD_CStream* cctx; } cRess_t; -static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, +static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, ZSTD_compressionParameters* comprParams, - unsigned long long const dictSize, + unsigned long long const dictSize, unsigned long long const maxSrcFileSize, int cLevel) { @@ -807,7 +807,7 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, if (fileWindowLog > ZSTD_WINDOWLOG_MAX) DISPLAYLEVEL(1, "Max window log exceeded by file (compression ratio will suffer)\n"); comprParams->windowLog = MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog); - if (fileWindowLog > ZSTD_cycleLog(comprParams->hashLog, cParams.strategy)) { + if (fileWindowLog > ZSTD_cycleLog(cParams.hashLog, cParams.strategy)) { if (!prefs->ldmFlag) DISPLAYLEVEL(1, "long mode automaticaly triggered\n"); FIO_setLdmFlag(prefs, 1); @@ -898,7 +898,7 @@ static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, } else { CHECK( ZSTD_CCtx_loadDictionary(ress.cctx, ress.dictBuffer, ress.dictBufferSize) ); } - + return ress; } @@ -1724,7 +1724,7 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi if (prefs->patchFromMode) FIO_adjustMemLimitForPatchFromMode(prefs, UTIL_getFileSize(dictFileName), 0 /* just use the dict size */); - + /* Allocation */ ress.dctx = ZSTD_createDStream(); if (ress.dctx==NULL) From dba02245bf41e078764e18683e4ff0f0883599e3 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 21 Apr 2020 20:31:11 -0700 Subject: [PATCH 285/402] bash to shell conversion --- tests/playTests.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index 0276f58e1fe..3c91b958f18 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -1280,8 +1280,7 @@ println "\n===> patch-from long mode trigger larger file test" datagen -g5000000 > tmp_dict datagen -g5000000 > tmp_patch -zstd -15 --patch-from=tmp_dict tmp_patch &> tmp_out -grep "long mode automaticaly triggered" tmp_out +zstd -15 --patch-from=tmp_dict tmp_patch 2>&1 | grep "long mode automaticaly triggered" rm -rf tmp* println "\n===> large files tests " From f7a7409a49307c43afc624fa7ce1596bbad9080f Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 21 Apr 2020 22:26:48 -0700 Subject: [PATCH 286/402] adding fail test when passing wrong fullDict using refPrefix --- tests/fuzzer.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index c62fd2f9d81..fc95028f324 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2532,6 +2532,41 @@ static int basicUnitTests(U32 const seed, double compressibility) FSE_normalizeCount(norm, tableLog, count, nbSeq, maxSymbolValue); } DISPLAYLEVEL(3, "OK \n"); +#ifdef ZSTD_MULTITHREAD + DISPLAYLEVEL(3, "test%3i passing wrong full dict should fail on compressStream2 refPrefix ", testNb++); + { + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + /* A little more than ZSTDMT_JOBSIZE_MIN */ + size_t const srcSize = 1 MB + 5; + size_t const dstSize = ZSTD_compressBound(srcSize); + void* const src = CNBuffer; + void* const dst = compressedBuffer; + void* dict = (void*)malloc(srcSize); + + RDG_genBuffer(src, srcSize, compressibility, 0.5, seed); + RDG_genBuffer(dict, srcSize, compressibility, 0., seed); + + /* Make sure there is no ZSTD_MAGIC_NUMBER */ + memset(dict, 0, sizeof(U32)); + + /* something more than 1 */ + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2)); + /* lie and claim this is a full dict */ + CHECK_Z(ZSTD_CCtx_refPrefix_advanced(cctx, dict, srcSize, ZSTD_dct_fullDict)); + + { + ZSTD_outBuffer out = {dst, dstSize, 0}; + ZSTD_inBuffer in = {src, srcSize, 0}; + + /* should fail because its not a full dict like we said it was */ + assert(ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush))); + } + + ZSTD_freeCCtx(cctx); + free(dict); + } + DISPLAYLEVEL(3, "OK \n"); +#endif DISPLAYLEVEL(3, "test%3i : table cleanliness through index reduction : ", testNb++); { From 1875f616ce98755c2bc8d14061ee2ae222c2395b Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 21 Apr 2020 22:29:35 -0700 Subject: [PATCH 287/402] passing dictContentType instead of rawContent every time --- lib/compress/zstd_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d458b84461c..552ca9fb44d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3965,7 +3965,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, ZSTD_dct_rawContent, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) ); cctx->streamStage = zcss_load; cctx->appliedParams.nbWorkers = params.nbWorkers; From b104f8e3eb3fdd98f09fd97dbb2a1a48dd022586 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 27 Apr 2020 12:12:28 -0700 Subject: [PATCH 288/402] [zstd] Fix typo in ZSTD_dParameter --- lib/zstd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstd.h b/lib/zstd.h index 6da84e27098..ae99b3039ba 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -522,7 +522,7 @@ typedef enum { /* note : additional experimental parameters are also available * within the experimental section of the API. * At the time of this writing, they include : - * ZSTD_c_format + * ZSTD_d_format * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly */ From a4ff217baf0c83f93ab16d8f406cee69cadf495f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 27 Apr 2020 17:42:03 -0700 Subject: [PATCH 289/402] [lib] Add ZSTD_d_stableOutBuffer --- lib/common/error_private.c | 1 + lib/common/zstd_errors.h | 1 + lib/decompress/zstd_decompress.c | 97 ++++++++++++++++++----- lib/decompress/zstd_decompress_internal.h | 7 ++ lib/zstd.h | 27 ++++++- tests/zstreamtest.c | 86 ++++++++++++++++++++ 6 files changed, 198 insertions(+), 21 deletions(-) diff --git a/lib/common/error_private.c b/lib/common/error_private.c index 39205844091..cd437529c12 100644 --- a/lib/common/error_private.c +++ b/lib/common/error_private.c @@ -47,6 +47,7 @@ const char* ERR_getErrorString(ERR_enum code) /* following error codes are not stable and may be removed or changed in a future version */ case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; + case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong"; case PREFIX(maxCode): default: return notErrorCode; } diff --git a/lib/common/zstd_errors.h b/lib/common/zstd_errors.h index 238309457b3..998398e7e57 100644 --- a/lib/common/zstd_errors.h +++ b/lib/common/zstd_errors.h @@ -76,6 +76,7 @@ typedef enum { /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */ ZSTD_error_frameIndex_tooLarge = 100, ZSTD_error_seekableIO = 102, + ZSTD_error_dstBuffer_wrong = 104, ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ } ZSTD_ErrorCode; diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 6ef156b658d..9cd637354ac 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -113,6 +113,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->noForwardProgress = 0; dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); + dctx->outBufferMode = ZSTD_obm_buffered; } ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) @@ -1402,6 +1403,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) bounds.upperBound = (int)ZSTD_f_zstd1_magicless; ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); return bounds; + case ZSTD_d_stableOutBuffer: + bounds.lowerBound = (int)ZSTD_obm_buffered; + bounds.upperBound = (int)ZSTD_obm_stable; + return bounds; default:; } bounds.error = ERROR(parameter_unsupported); @@ -1437,6 +1442,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value CHECK_DBOUNDS(ZSTD_d_format, value); dctx->format = (ZSTD_format_e)value; return 0; + case ZSTD_d_stableOutBuffer: + CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value); + dctx->outBufferMode = (ZSTD_outBufferMode_e)value; + return 0; default:; } RETURN_ERROR(parameter_unsupported); @@ -1517,6 +1526,50 @@ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds) return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION; } +static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output) +{ + ZSTD_outBuffer const expect = zds->expectedOutBuffer; + /* No requirement when ZSTD_obm_stable is not enabled. */ + if (zds->outBufferMode != ZSTD_obm_stable) + return 0; + /* Any buffer is allowed in zdss_init, this must be the same for every other call until + * the context is reset. + */ + if (zds->streamStage == zdss_init) + return 0; + /* The buffer must match our expectation exactly. */ + if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size) + return 0; + RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!"); +} + +static size_t ZSTD_decompressContinueStream( + ZSTD_DStream* zds, char** op, char* oend, + void const* src, size_t srcSize) { + int const isSkipFrame = ZSTD_isSkipFrame(zds); + if (zds->outBufferMode == ZSTD_obm_buffered) { + size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart; + size_t const decodedSize = ZSTD_decompressContinue(zds, + zds->outBuff + zds->outStart, dstSize, src, srcSize); + FORWARD_IF_ERROR(decodedSize); + if (!decodedSize && !isSkipFrame) { + zds->streamStage = zdss_read; + } else { + zds->outEnd = zds->outStart + decodedSize; + zds->streamStage = zdss_flush; + } + } else { + size_t const dstSize = isSkipFrame ? 0 : oend - *op; + size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); + FORWARD_IF_ERROR(decodedSize); + *op += decodedSize; + zds->streamStage = zdss_read; + assert(*op <= oend); + assert(zds->outBufferMode == ZSTD_obm_stable); + } + return 0; +} + size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { const char* const src = (const char*)input->src; @@ -1541,6 +1594,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB "forbidden. out: pos: %u vs size: %u", (U32)output->pos, (U32)output->size); DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos)); + FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output)); while (someMoreWork) { switch(zds->streamStage) @@ -1551,6 +1605,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; zds->legacyVersion = 0; zds->hostageByte = 0; + zds->expectedOutBuffer = *output; /* fall-through */ case zdss_loadHeader : @@ -1621,6 +1676,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB break; } } + /* Check output buffer is large enough for ZSTD_odm_stable. */ + if (zds->outBufferMode == ZSTD_obm_stable + && zds->fParams.frameType != ZSTD_skippableFrame + && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN + && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) { + RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small"); + } + /* Consume header (see ZSTDds_decodeFrameHeader) */ DEBUGLOG(4, "Consume header"); FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds))); @@ -1644,7 +1707,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); - size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); + size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered + ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize) + : 0; ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize); @@ -1687,15 +1752,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB break; } if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */ - int const isSkipFrame = ZSTD_isSkipFrame(zds); - size_t const decodedSize = ZSTD_decompressContinue(zds, - zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), - ip, neededInSize); - if (ZSTD_isError(decodedSize)) return decodedSize; + FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize)); ip += neededInSize; - if (!decodedSize && !isSkipFrame) break; /* this was just a header */ - zds->outEnd = zds->outStart + decodedSize; - zds->streamStage = zdss_flush; + /* Function modifies the stage so we must break */ break; } } if (ip==iend) { someMoreWork = 0; break; } /* no more input */ @@ -1722,17 +1781,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */ /* decode loaded input */ - { size_t const decodedSize = ZSTD_decompressContinue(zds, - zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart, - zds->inBuff, neededInSize); - if (ZSTD_isError(decodedSize)) return decodedSize; - zds->inPos = 0; /* input is consumed */ - if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */ - zds->outEnd = zds->outStart + decodedSize; - } } - zds->streamStage = zdss_flush; - /* fall-through */ - + zds->inPos = 0; /* input is consumed */ + FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize)); + /* Function modifies the stage so we must break */ + break; + } case zdss_flush: { size_t const toFlushSize = zds->outEnd - zds->outStart; size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize); @@ -1761,6 +1814,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* result */ input->pos = (size_t)(ip - (const char*)(input->src)); output->pos = (size_t)(op - (char*)(output->dst)); + + /* Update the expected output buffer for ZSTD_obm_stable. */ + zds->expectedOutBuffer = *output; + if ((ip==istart) && (op==ostart)) { /* no forward progress */ zds->noForwardProgress ++; if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) { diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 29b4d0acc21..f1c2585a662 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -95,6 +95,11 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; +typedef enum { + ZSTD_obm_buffered = 0, /* Buffer the output */ + ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */ +} ZSTD_outBufferMode_e; + struct ZSTD_DCtx_s { const ZSTD_seqSymbol* LLTptr; @@ -147,6 +152,8 @@ struct ZSTD_DCtx_s U32 legacyVersion; U32 hostageByte; int noForwardProgress; + ZSTD_outBufferMode_e outBufferMode; + ZSTD_outBuffer expectedOutBuffer; /* workspace */ BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; diff --git a/lib/zstd.h b/lib/zstd.h index ae99b3039ba..40e9fb162c3 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -523,10 +523,12 @@ typedef enum { * within the experimental section of the API. * At the time of this writing, they include : * ZSTD_d_format + * ZSTD_d_stableOutBuffer * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly */ - ZSTD_d_experimentalParam1=1000 + ZSTD_d_experimentalParam1=1000, + ZSTD_d_experimentalParam2=1001 } ZSTD_dParameter; @@ -1645,6 +1647,29 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS * allowing selection between ZSTD_format_e input compression formats */ #define ZSTD_d_format ZSTD_d_experimentalParam1 +/* ZSTD_d_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same + * between calls, except for the modifications that zstd makes to pos (the + * caller must not modify pos). This is checked by the decompressor, and + * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer + * MUST be large enough to fit the entire decompressed frame. This will be + * checked when the frame content size is known. + * + * When this flags is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer, but it will still allocate + * an input buffer large enough to fit any compressed block. This will also + * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer. + * If you need to avoid the input buffer allocation use the buffer-less + * streaming API. + * + * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, decompression WILL fail if you violate the preconditions. + */ +#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 /*! ZSTD_DCtx_setFormat() : * Instruct the decoder context about what kind of data to decode next. diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index a945125ac99..002c16de957 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -641,6 +641,92 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + /* Decompression with ZSTD_d_stableOutBuffer */ + cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1); + CHECK_Z(cSize); + { ZSTD_DCtx* dctx = ZSTD_createDCtx(); + size_t const dctxSize0 = ZSTD_sizeof_DCtx(dctx); + size_t dctxSize1; + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); + + outBuff.dst = decodedBuffer; + outBuff.pos = 0; + outBuff.size = CNBufferSize; + + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() single pass : ", testNb++); + inBuff.src = compressedBuffer; + inBuff.size = cSize; + inBuff.pos = 0; + { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); + CHECK_Z(r); + CHECK(r != 0, "Entire frame must be decompressed"); + CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); + CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); + } + CHECK(dctxSize0 != ZSTD_sizeof_DCtx(dctx), "No buffers allocated"); + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer : ", testNb++); + outBuff.pos = 0; + inBuff.pos = 0; + inBuff.size = 0; + while (inBuff.pos < cSize) { + inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15)); + CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); + } + CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); + CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); + dctxSize1 = ZSTD_sizeof_DCtx(dctx); + CHECK(!(dctxSize0 < dctxSize1), "Input buffer allocated"); + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer too small : ", testNb++); + ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); + inBuff.src = compressedBuffer; + inBuff.size = cSize; + inBuff.pos = 0; + outBuff.pos = 0; + outBuff.size = CNBufferSize - 1; + { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); + CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall, "Must error but got %s", ZSTD_getErrorName(r)); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer modified : ", testNb++); + ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); + inBuff.src = compressedBuffer; + inBuff.size = cSize - 1; + inBuff.pos = 0; + outBuff.pos = 0; + outBuff.size = CNBufferSize; + CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); + ++inBuff.size; + outBuff.pos = 0; + { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); + CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstBuffer_wrong, "Must error but got %s", ZSTD_getErrorName(r)); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() buffered output : ", testNb++); + ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only); + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 0)); + outBuff.pos = 0; + inBuff.pos = 0; + inBuff.size = 0; + while (inBuff.pos < cSize) { + inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15)); + CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff)); + } + CHECK(outBuff.pos != CNBufferSize, "Wrong size!"); + CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); + CHECK(!(dctxSize1 < ZSTD_sizeof_DCtx(dctx)), "Output buffer allocated"); + DISPLAYLEVEL(3, "OK \n"); + + ZSTD_freeDCtx(dctx); + } + /* CDict scenario */ DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++); { ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ ); From f33de06c3ecdd1bce5a8f7c2b500cb2e239a1bdd Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 27 Apr 2020 18:10:45 -0700 Subject: [PATCH 290/402] [lib] Fix single-pass mode for empty frames --- lib/decompress/zstd_decompress.c | 3 ++- tests/zstreamtest.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 9cd637354ac..ed82f9e010f 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1660,7 +1660,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } /* check for single-pass mode opportunity */ - if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */ + if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN + && zds->fParams.frameType != ZSTD_skippableFrame && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) { size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); if (cSize <= (size_t)(iend-istart)) { diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 002c16de957..31cf0a17322 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -641,6 +641,32 @@ static int basicUnitTests(U32 seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + /* Decompression single pass with empty frame */ + cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, NULL, 0, 1); + CHECK_Z(cSize); + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() single pass on empty frame : ", testNb++); + { ZSTD_DCtx* dctx = ZSTD_createDCtx(); + size_t const dctxSize = ZSTD_sizeof_DCtx(dctx); + CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1)); + + outBuff.dst = decodedBuffer; + outBuff.pos = 0; + outBuff.size = CNBufferSize; + + inBuff.src = compressedBuffer; + inBuff.size = cSize; + inBuff.pos = 0; + { size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff); + CHECK_Z(r); + CHECK(r != 0, "Entire frame must be decompressed"); + CHECK(outBuff.pos != 0, "Wrong size!"); + CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!"); + } + CHECK(dctxSize != ZSTD_sizeof_DCtx(dctx), "No buffers allocated"); + ZSTD_freeDCtx(dctx); + } + DISPLAYLEVEL(3, "OK \n"); + /* Decompression with ZSTD_d_stableOutBuffer */ cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1); CHECK_Z(cSize); From 77a2945c433e70b50b5e1060e69603f7780a6286 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 27 Apr 2020 18:25:30 -0700 Subject: [PATCH 291/402] Add some comments --- lib/decompress/zstd_decompress.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index ed82f9e010f..8353099b3fe 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1526,6 +1526,7 @@ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds) return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION; } +/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output) { ZSTD_outBuffer const expect = zds->expectedOutBuffer; @@ -1543,6 +1544,11 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!"); } +/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream() + * and updates the stage and the output buffer state. This call is extracted so it can be + * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode. + * NOTE: You must break after calling this function since the streamStage is modified. + */ static size_t ZSTD_decompressContinueStream( ZSTD_DStream* zds, char** op, char* oend, void const* src, size_t srcSize) { @@ -1559,10 +1565,12 @@ static size_t ZSTD_decompressContinueStream( zds->streamStage = zdss_flush; } } else { + /* Write directly into the output buffer */ size_t const dstSize = isSkipFrame ? 0 : oend - *op; size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); FORWARD_IF_ERROR(decodedSize); *op += decodedSize; + /* Flushing is not needed. */ zds->streamStage = zdss_read; assert(*op <= oend); assert(zds->outBufferMode == ZSTD_obm_stable); From 1343b815f8c602612a70e84700ae65e959503a0b Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 27 Apr 2020 18:25:47 -0700 Subject: [PATCH 292/402] [fuzz] Fuzz test ZSTD_d_stableOutBuffer --- tests/fuzz/stream_decompress.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/fuzz/stream_decompress.c b/tests/fuzz/stream_decompress.c index df3b009aee8..503d32d6614 100644 --- a/tests/fuzz/stream_decompress.c +++ b/tests/fuzz/stream_decompress.c @@ -70,6 +70,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) * buffers in a row. */ int prevInWasZero = 0; int prevOutWasZero = 0; + int stableOutBuffer; + ZSTD_outBuffer out; size = FUZZ_dataProducer_reserveDataPrefix(producer); /* Allocate all buffers and contexts if not already allocated */ @@ -85,11 +87,21 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_ZASSERT(ZSTD_DCtx_reset(dstream, ZSTD_reset_session_only)); } + stableOutBuffer = FUZZ_dataProducer_uint32Range(producer, 0, 10) == 5; + if (stableOutBuffer) { + FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dstream, ZSTD_d_stableOutBuffer, 1)); + out.dst = buf; + out.size = kBufSize; + out.pos = 0; + } + while (size > 0) { ZSTD_inBuffer in = makeInBuffer(&src, &size, producer, prevInWasZero ? 1 : 0); prevInWasZero = in.size == 0; while (in.pos != in.size) { - ZSTD_outBuffer out = makeOutBuffer(producer, prevOutWasZero ? 1 : 0); + if (!stableOutBuffer || FUZZ_dataProducer_uint32Range(producer, 0, 100) == 55) { + out = makeOutBuffer(producer, prevOutWasZero ? 1 : 0); + } prevOutWasZero = out.size == 0; size_t const rc = ZSTD_decompressStream(dstream, &out, &in); if (ZSTD_isError(rc)) goto error; From 55a57d46bee541e71a0b4e34aa309665b07e51c9 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 28 Apr 2020 12:07:42 -0700 Subject: [PATCH 293/402] Add extra warnings about not modifying the ZSTD_outBuffer --- lib/zstd.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/zstd.h b/lib/zstd.h index 40e9fb162c3..18c20c87e3e 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1656,7 +1656,9 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS * caller must not modify pos). This is checked by the decompressor, and * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer * MUST be large enough to fit the entire decompressed frame. This will be - * checked when the frame content size is known. + * checked when the frame content size is known. The data in the ZSTD_outBuffer + * in the range [dst, dst + pos) MUST not be modified during decompression + * or you will get data corruption. * * When this flags is enabled zstd won't allocate an output buffer, because * it can write directly to the ZSTD_outBuffer, but it will still allocate @@ -1668,6 +1670,12 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using * this flag is ALWAYS memory safe, and will never access out-of-bounds * memory. However, decompression WILL fail if you violate the preconditions. + * + * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST + * not be modified during decompression or you will get data corruption. This + * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate + * matches. Normally zstd maintains its own buffer for this purpose, but passing + * this flag tells zstd to use the user provided buffer. */ #define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 From f17ac423b21fffdc2918daafe41a5eae0478b249 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 Apr 2020 15:58:22 -0700 Subject: [PATCH 294/402] new tests created new artifacts they were not properly ignored --- tests/.gitignore | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index 4edf6ce1383..9a6939a5766 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -29,40 +29,40 @@ zcat zstdcat tm +# test artifacts +dictionary +grillResults.txt +_* +tmp* +*.zst +*.gz +!gzip/hufts-segv.gz +result +out +*.zstd +hello* +world + # Tmp test directory zstdtest speedTest versionsTest namespaceTest +dirTest* + +# fuzzer +afl # Local script startSpeedTest speedTest.pid +*.bat -# Object files +# Generic Object files *.o *.ko -# Executables +# Generic Executables *.exe *.out *.app - -# Default result files -dictionary -grillResults.txt -_* -tmp* -*.zst -*.gz -!gzip/hufts-segv.gz -result -out -*.zstd - -# fuzzer -afl - -# Misc files -*.bat -dirTest* From c6ae2e83bcf9da8869364921db39ebd317faf7d4 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 Apr 2020 18:29:20 -0700 Subject: [PATCH 295/402] fix libzstd-mt underlinking issue fix #2045 When compiling `libzstd` in multithreading mode, the `libzstd-mt` recipe would not include `-pthread`, resulting in an underlinked dynamic library. Added a test on Travis to check that the library is fully linked. This makes it possible, in some future release, to build a multi-threaded `libzstd` dynamic library by default as it would no longer impact the build script of user programs. --- .travis.yml | 4 +++- lib/Makefile | 18 +++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4e45560260..31fc42571cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,12 +56,14 @@ matrix: # DEVNULLRIGHTS : will request sudo rights to test permissions on /dev/null - DEVNULLRIGHTS=test make test - - name: gcc-6 + gcc-7 compilation # ~ 3mn + - name: gcc-6 + gcc-7 + libzstdmt compilation # ~ 6mn script: - make gcc6install gcc7install - CC=gcc-6 CFLAGS=-Werror make -j all - make clean - CC=gcc-7 CFLAGS=-Werror make -j all + - make clean + - LDFLAGS=-Wl,--no-undefined make -C lib libzstd-mt - name: gcc-8 + ASan + UBSan + Test Zstd # ~6.5mn script: diff --git a/lib/Makefile b/lib/Makefile index fc7daf0804e..7a05b158d99 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -154,9 +154,6 @@ libzstd.a: $(ZSTD_OBJ) @echo compiling static library @$(AR) $(ARFLAGS) $@ $^ -libzstd.a-mt: CPPFLAGS += -DZSTD_MULTITHREAD -libzstd.a-mt: libzstd.a - ifneq (,$(filter Windows%,$(OS))) LIBZSTD = dll\libzstd.dll @@ -180,17 +177,20 @@ endif libzstd : $(LIBZSTD) -libzstd-mt : CPPFLAGS += -DZSTD_MULTITHREAD +lib : libzstd.a libzstd + +%-mt : CPPFLAGS += -DZSTD_MULTITHREAD +%-mt : LDFLAGS += -pthread + libzstd-mt : libzstd -lib: libzstd.a libzstd +libzstd.a-mt: libzstd.a -lib-mt: CPPFLAGS += -DZSTD_MULTITHREAD -lib-mt: lib +lib-mt : lib -lib-release lib-release-mt: DEBUGFLAGS := +%-release : DEBUGFLAGS := lib-release: lib -lib-release-mt: lib-mt +lib-mt-release : lib-mt # Special case : building library in single-thread mode _and_ without zstdmt_compress.c ZSTDMT_FILES = compress/zstdmt_compress.c From f77fd5ced0042bcccdb68f387c725e3ee142589c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 Apr 2020 18:43:55 -0700 Subject: [PATCH 296/402] generalized pattern rules --- lib/Makefile | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 7a05b158d99..ac38867a931 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -181,16 +181,13 @@ lib : libzstd.a libzstd %-mt : CPPFLAGS += -DZSTD_MULTITHREAD %-mt : LDFLAGS += -pthread - -libzstd-mt : libzstd - -libzstd.a-mt: libzstd.a - -lib-mt : lib +%-mt : % + @echo multi-threading build completed %-release : DEBUGFLAGS := -lib-release: lib -lib-mt-release : lib-mt +%-release : % + @echo release build completed + # Special case : building library in single-thread mode _and_ without zstdmt_compress.c ZSTDMT_FILES = compress/zstdmt_compress.c From 7ea2ae66495854346ae7cd26ab926859f410d492 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 28 Apr 2020 21:18:29 -0700 Subject: [PATCH 297/402] added test linking user program to multi-threaded libzstd --- .travis.yml | 3 +++ programs/Makefile | 22 +++++++++++++++++++--- tests/Makefile | 22 ++++++++++------------ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 31fc42571cc..aeaae729269 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,9 @@ matrix: - CC=gcc-7 CFLAGS=-Werror make -j all - make clean - LDFLAGS=-Wl,--no-undefined make -C lib libzstd-mt + - make -C tests zbufftest-dll + # LDFLAGS=-Wl,--no-undefined : will make the linker fail if dll is underlinked + # zbufftest-dll : test that a user program can link to multi-threaded libzstd without specifying -pthread - name: gcc-8 + ASan + UBSan + Test Zstd # ~6.5mn script: diff --git a/programs/Makefile b/programs/Makefile index 8146732b507..3366c093ed4 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -79,6 +79,9 @@ endif # Sort files in alphabetical order for reproducible builds ZSTDLIB_FILES := $(sort $(wildcard $(ZSTD_FILES)) $(wildcard $(ZSTDLEGACY_FILES)) $(wildcard $(ZDICT_FILES))) +ZSTD_CLI_FILES := $(wildcard *.c) +ZSTD_CLI_OBJ := $(patsubst %.c,%.o,$(ZSTD_CLI_FILES)) + # Define *.exe as extension for Windows systems ifneq (,$(filter Windows%,$(OS))) EXT =.exe @@ -172,7 +175,7 @@ zstd : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) ifneq (,$(filter Windows%,$(OS))) zstd : $(RES_FILE) endif -zstd : $(ZSTDLIB_FILES) zstdcli.o util.o timefn.o fileio.o benchfn.o benchzstd.o datagen.o dibio.o +zstd : $(ZSTDLIB_FILES) $(ZSTD_CLI_OBJ) @echo "$(THREAD_MSG)" @echo "$(ZLIB_MSG)" @echo "$(LZMA_MSG)" @@ -190,10 +193,10 @@ zstd32 : CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) ifneq (,$(filter Windows%,$(OS))) zstd32 : $(RES32_FILE) endif -zstd32 : $(ZSTDLIB_FILES) zstdcli.c util.c timefn.c fileio.c benchfn.c benchzstd.c datagen.c dibio.c +zstd32 : $(ZSTDLIB_FILES) $(ZSTD_CLI_FILES) $(CC) -m32 $(FLAGS) $^ -o $@$(EXT) -zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) zstdcli.o util.o fileio.c benchfn.o benchzstd.o timefn.o datagen.o dibio.o +zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) $(ZSTD_CLI_OBJ) $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) zstd-nomt : THREAD_CPP := @@ -211,6 +214,19 @@ zstd-noxz : LZMALD := zstd-noxz : LZMA_MSG := - xz/lzma support is disabled zstd-noxz : zstd +# note : the following target doesn't build +# because zstd uses non-public symbols from libzstd +# such as XXH64 (for benchmark), +# ZDICT_trainFromBuffer_unsafe_legacy for dictionary builder +# and ZSTD_cycleLog (likely for --patch-from) +# It's unclear at this stage if this is a scenario we want to support +## zstd-dll: zstd executable linked to dynamic library libzstd (must already exist) +.PHONY: zstd-dll +zstd-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd +zstd-dll : ZSTDLIB_FILES = +zstd-dll : $(ZSTD_CLI_OBJ) + $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) + zstd-pgo : $(MAKE) clean diff --git a/tests/Makefile b/tests/Makefile index 3d007471085..d347a948a6c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -91,6 +91,7 @@ allnothread: MULTITHREAD_CPP= allnothread: MULTITHREAD_LD= allnothread: fullbench fuzzer paramgrill datagen decodecorpus +# note : broken : requires symbols unavailable from dynamic library dll: fuzzer-dll zstreamtest-dll PHONY: zstd zstd32 zstd-nolegacy # must be phony, only external makefile knows how to build them, or if they need an update @@ -98,12 +99,15 @@ zstd zstd32 zstd-nolegacy: $(MAKE) -C $(PRGDIR) $@ MOREFLAGS+="$(DEBUGFLAGS)" gzstd: - $(MAKE) -C $(PRGDIR) zstd HAVE_ZLIB=1 MOREFLAGS+="$(DEBUGFLAGS)" + $(MAKE) -C $(PRGDIR) $@ HAVE_ZLIB=1 MOREFLAGS+="$(DEBUGFLAGS)" -.PHONY: zstd-dll -zstd-dll : +.PHONY: libzstd +libzstd : $(MAKE) -C $(ZSTDDIR) libzstd +%-dll : libzstd +%-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd + .PHONY: zstd-staticLib zstd-staticLib : $(MAKE) -C $(ZSTDDIR) libzstd.a @@ -141,9 +145,7 @@ fullbench-lib : zstd-staticLib fullbench-lib : $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/benchfn.c fullbench.c $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) $(ZSTDDIR)/libzstd.a -# note : broken : requires unavailable symbols -fullbench-dll : zstd-dll -fullbench-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd +# note : broken : requires symbols unavailable from dynamic library fullbench-dll: $(PRGDIR)/datagen.c $(PRGDIR)/util.c $(PRGDIR)/benchfn.c $(PRGDIR)/timefn.c fullbench.c # $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) -DZSTD_DLL_IMPORT=1 $(ZSTDDIR)/dll/libzstd.dll $(CC) $(FLAGS) $(filter %.c,$^) -o $@$(EXT) @@ -156,8 +158,7 @@ fuzzer32: $(ZSTD_FILES) fuzzer fuzzer32 : $(ZDICT_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c $(CC) $(FLAGS) $^ -o $@$(EXT) -fuzzer-dll : zstd-dll -fuzzer-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd +# note : broken : requires symbols unavailable from dynamic library fuzzer-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c fuzzer.c $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) @@ -167,8 +168,6 @@ zbufftest32 : CFLAGS += -m32 zbufftest zbufftest32 : $(ZSTD_OBJECTS) $(ZBUFF_FILES) $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c $(CC) $(FLAGS) $^ -o $@$(EXT) -zbufftest-dll : zstd-dll -zbufftest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd zbufftest-dll : $(ZSTDDIR)/common/xxhash.c $(PRGDIR)/util.c $(PRGDIR)/timefn.c $(PRGDIR)/datagen.c zbufftest.c $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) @@ -191,8 +190,7 @@ zstreamtest_tsan : CFLAGS += -fsanitize=thread zstreamtest_tsan : $(ZSTREAMFILES) $(CC) $(FLAGS) $(MULTITHREAD) $^ -o $@$(EXT) -zstreamtest-dll : zstd-dll -zstreamtest-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd +# note : broken : requires symbols unavailable from dynamic library zstreamtest-dll : $(ZSTDDIR)/common/xxhash.c # xxh symbols not exposed from dll zstreamtest-dll : $(ZSTREAM_LOCAL_FILES) $(CC) $(CPPFLAGS) $(CFLAGS) $(filter %.c,$^) $(LDFLAGS) -o $@$(EXT) From 6f62a9caaa8fa2d7c877c1357b537ee9f37ccc12 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Wed, 29 Apr 2020 11:56:21 -0700 Subject: [PATCH 298/402] fixed zstd-nolegacy target when compiled as part of allVariants (though I'm unsure why it was working before ...) --- programs/Makefile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index 3366c093ed4..abad6da6b96 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -196,6 +196,8 @@ endif zstd32 : $(ZSTDLIB_FILES) $(ZSTD_CLI_FILES) $(CC) -m32 $(FLAGS) $^ -o $@$(EXT) +## zstd-nolegacy: same scope as zstd, with just support of legacy formats removed +zstd-nolegacy : LDFLAGS += $(THREAD_LD) $(ZLIBLD) $(LZMALD) $(LZ4LD) $(DEBUGFLAGS_LD) zstd-nolegacy : $(ZSTD_FILES) $(ZDICT_FILES) $(ZSTD_CLI_OBJ) $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) @@ -240,7 +242,7 @@ zstd-pgo : $(RM) zstd *.o $(ZSTDDECOMP_O) $(ZSTDDIR)/compress/*.o $(MAKE) zstd MOREFLAGS=-fprofile-use -# minimal target, with only zstd compression and decompression. no bench. no legacy. +## zstd-small: minimal target, supporting only zstd compression and decompression. no bench. no legacy. no other format. zstd-small: CFLAGS = -Os -s zstd-frugal zstd-small: $(ZSTD_FILES) zstdcli.c util.c timefn.c fileio.c $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT $^ -o $@$(EXT) @@ -251,6 +253,7 @@ zstd-decompress: $(ZSTDCOMMON_FILES) $(ZSTDDECOMP_FILES) zstdcli.c util.c timefn zstd-compress: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) zstdcli.c util.c timefn.c fileio.c $(CC) $(FLAGS) -DZSTD_NOBENCH -DZSTD_NODICT -DZSTD_NODECOMPRESS $^ -o $@$(EXT) +## zstd-dictBuilder: executable supporting dictionary creation and compression (only) zstd-dictBuilder: CPPFLAGS += -DZSTD_NOBENCH -DZSTD_NODECOMPRESS zstd-dictBuilder: $(ZSTDCOMMON_FILES) $(ZSTDCOMP_FILES) $(ZDICT_FILES) zstdcli.c util.c timefn.c fileio.c dibio.c $(CC) $(FLAGS) $^ -o $@$(EXT) @@ -318,6 +321,7 @@ ifeq ($HAVE_COLORNEVER, 1) EGREP_OPTIONS += --color=never endif EGREP = egrep $(EGREP_OPTIONS) +AWK = awk # Print a two column output of targets and their description. To add a target description, put a # comment in the Makefile with the format "## : ". For example: @@ -326,14 +330,14 @@ EGREP = egrep $(EGREP_OPTIONS) .PHONY: list list: @TARGETS=$$($(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null \ - | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \ + | $(AWK) -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \ | $(EGREP) -v -e '^[^[:alnum:]]' | sort); \ { \ printf "Target Name\tDescription\n"; \ printf "%0.s-" {1..16}; printf "\t"; printf "%0.s-" {1..40}; printf "\n"; \ for target in $$TARGETS; do \ line=$$($(EGREP) "^##[[:space:]]+$$target:" $(lastword $(MAKEFILE_LIST))); \ - description=$$(echo $$line | awk '{i=index($$0,":"); print substr($$0,i+1)}' | xargs); \ + description=$$(echo $$line | $(AWK) '{i=index($$0,":"); print substr($$0,i+1)}' | xargs); \ printf "$$target\t$$description\n"; \ done \ } | column -t -s $$'\t' From 834a8f838a3ba3ba7e24462829b40189f4b70e99 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Fri, 1 May 2020 09:04:09 -0500 Subject: [PATCH 299/402] meson msvc build fix --- build/meson/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/meson/meson.build b/build/meson/meson.build index 121811e7265..970cf3c92b9 100644 --- a/build/meson/meson.build +++ b/build/meson/meson.build @@ -68,6 +68,7 @@ zstd_docdir = join_paths(zstd_datadir, 'doc', meson.project_name()) # Built-in options use_debug = get_option('debug') buildtype = get_option('buildtype') +default_library_type = get_option('default_library') # Custom options debug_level = get_option('debug_level') @@ -121,7 +122,7 @@ elif cc_id == compiler_msvc if use_multi_thread msvc_compile_flags += '/MP' endif - if enable_static_runtime + if use_static_runtime msvc_compile_flags += '/MT' endif add_project_arguments(msvc_compile_flags, language: ['c', 'cpp']) From fdb2780c47727eb8ec0fb354dfc4c6730bbd67d1 Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Sat, 1 Feb 2020 11:56:31 -0800 Subject: [PATCH 300/402] Move rank table into HUF_buildCTable_wksp() --- lib/compress/huf_compress.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 5cab31d042f..f81a2f38672 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -295,12 +295,11 @@ typedef struct { U32 current; } rankPos; -static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue) +static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rank) { - rankPos rank[32]; U32 n; - memset(rank, 0, sizeof(rank)); + memset(rank, 0, sizeof(rankPos)*32); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); rank[r].base ++; @@ -335,6 +334,7 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo int lowS, lowN; U16 nodeNb = STARTNODE; U32 nodeRoot; + rankPos rank[32]; /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ @@ -344,7 +344,7 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo memset(huffNode0, 0, sizeof(huffNodeTable)); /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue); + HUF_sort(huffNode, count, maxSymbolValue, rank); /* init for parents */ nonNullRank = maxSymbolValue; From a084d959bdba329b4fce512e7ca1b8c8208cc371 Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Sat, 1 Feb 2020 12:41:05 -0800 Subject: [PATCH 301/402] WIP: Increased wksp size, but it's segfaulting --- lib/common/huf.h | 2 +- lib/compress/huf_compress.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/common/huf.h b/lib/common/huf.h index 0d27ccdba94..53b1ad69373 100644 --- a/lib/common/huf.h +++ b/lib/common/huf.h @@ -90,7 +90,7 @@ HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, /** HUF_compress4X_wksp() : * Same as HUF_compress2(), but uses externally allocated `workSpace`. * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */ -#define HUF_WORKSPACE_SIZE (6 << 10) +#define HUF_WORKSPACE_SIZE ((6 << 10) + 256) #define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const void* src, size_t srcSize, diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index f81a2f38672..f0b21072544 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -299,7 +299,7 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu { U32 n; - memset(rank, 0, sizeof(rankPos)*32); + memset(rank, 0, sizeof(rankPos) * 32); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); rank[r].base ++; @@ -334,11 +334,11 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo int lowS, lowN; U16 nodeNb = STARTNODE; U32 nodeRoot; - rankPos rank[32]; - + rankPos* rank = (rankPos *)(huffNode + 1); + DEBUGLOG(3, "workspace %p huffnode0 %p huffnode %p rank %p workspaceend %p", workSpace, huffNode0, huffNode, rank, ((BYTE*)workSpace) + wkspSize); /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall); + if (wkspSize < sizeof(huffNodeTable) + sizeof(rankPos) * 32) return ERROR(workSpace_tooSmall); if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); memset(huffNode0, 0, sizeof(huffNodeTable)); @@ -403,8 +403,9 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo */ size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) { - huffNodeTable nodeTable; - return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable)); + U32 workspace[HUF_WORKSPACE_SIZE_U32]; + DEBUGLOG(3, "!!!"); + return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, workspace, sizeof(workspace)); } size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) From fe8402b5223c8b716e8c0b35884e317ae4478cef Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Sat, 1 Feb 2020 15:34:51 -0800 Subject: [PATCH 302/402] WIP: Still getting an error --- lib/compress/huf_compress.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index f0b21072544..179a68f45e7 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -334,8 +334,8 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo int lowS, lowN; U16 nodeNb = STARTNODE; U32 nodeRoot; - rankPos* rank = (rankPos *)(huffNode + 1); - DEBUGLOG(3, "workspace %p huffnode0 %p huffnode %p rank %p workspaceend %p", workSpace, huffNode0, huffNode, rank, ((BYTE*)workSpace) + wkspSize); + rankPos* rank = (rankPos *)(huffNode0 + HUF_CTABLE_WORKSPACE_SIZE / sizeof(nodeElt*)); + /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ if (wkspSize < sizeof(huffNodeTable) + sizeof(rankPos) * 32) return ERROR(workSpace_tooSmall); @@ -404,7 +404,6 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) { U32 workspace[HUF_WORKSPACE_SIZE_U32]; - DEBUGLOG(3, "!!!"); return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, workspace, sizeof(workspace)); } @@ -672,7 +671,7 @@ HUF_compress_internal (void* dst, size_t dstSize, huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, maxSymbolValue, huffLog, - table->nodeTable, sizeof(table->nodeTable)); + table->nodeTable, ((BYTE*)workSpace) + wkspSize - (BYTE*)table->nodeTable); CHECK_F(maxBits); huffLog = (U32)maxBits; /* Zero unused symbols in CTable, so we can check it for validity */ From cc7c29595d7591eb901973bf9c5fc6c854d086ca Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Sat, 1 Feb 2020 18:26:14 -0800 Subject: [PATCH 303/402] Fixed tests to use correct workspace size --- tests/decodecorpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/decodecorpus.c b/tests/decodecorpus.c index af961bfd0c7..a46fc24d897 100644 --- a/tests/decodecorpus.c +++ b/tests/decodecorpus.c @@ -185,7 +185,7 @@ BYTE SEQUENCE_LLCODE[ZSTD_BLOCKSIZE_MAX]; BYTE SEQUENCE_MLCODE[ZSTD_BLOCKSIZE_MAX]; BYTE SEQUENCE_OFCODE[ZSTD_BLOCKSIZE_MAX]; -unsigned WKSP[1024]; +unsigned WKSP[HUF_WORKSPACE_SIZE_U32]; typedef struct { size_t contentSize; /* 0 means unknown (unless contentSize == windowSize == 0) */ From 53d76dc20f57ee67d247be6d86d5372976eb84dd Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Thu, 27 Feb 2020 22:02:44 +0530 Subject: [PATCH 304/402] Remove magic constant and made other changes addressing the comments --- lib/compress/huf_compress.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 179a68f45e7..8f96484211f 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -289,28 +289,34 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) return maxNbBits; } - typedef struct { U32 base; U32 current; } rankPos; -static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rank) +typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; + +typedef struct { + rankPos rankPosition[32]; + huffNodeTable huffNodeTbl; +} HUF_buildCTable_wksp_tables; + +static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) { U32 n; - memset(rank, 0, sizeof(rankPos) * 32); + memset(rankPosition, 0, sizeof(*rankPosition)); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); - rank[r].base ++; + rankPosition[r].base ++; } - for (n=30; n>0; n--) rank[n-1].base += rank[n].base; - for (n=0; n<32; n++) rank[n].current = rank[n].base; + for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base; + for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base; for (n=0; n<=maxSymbolValue; n++) { U32 const c = count[n]; U32 const r = BIT_highbit32(c+1) + 1; - U32 pos = rank[r].current++; - while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) { + U32 pos = rankPosition[r].current++; + while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) { huffNode[pos] = huffNode[pos-1]; pos--; } @@ -325,26 +331,28 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned. */ #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) -typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; + size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) { - nodeElt* const huffNode0 = (nodeElt*)workSpace; + HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; + nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; nodeElt* const huffNode = huffNode0+1; U32 n, nonNullRank; int lowS, lowN; U16 nodeNb = STARTNODE; U32 nodeRoot; - rankPos* rank = (rankPos *)(huffNode0 + HUF_CTABLE_WORKSPACE_SIZE / sizeof(nodeElt*)); /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(huffNodeTable) + sizeof(rankPos) * 32) return ERROR(workSpace_tooSmall); + if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) + return ERROR(workSpace_tooSmall); if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) + return ERROR(maxSymbolValue_tooLarge); memset(huffNode0, 0, sizeof(huffNodeTable)); /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue, rank); + HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); /* init for parents */ nonNullRank = maxSymbolValue; From 0adfc8dfcef352e098446c59a14950bdf9b2028d Mon Sep 17 00:00:00 2001 From: Meghna Malhotra Date: Tue, 31 Mar 2020 22:46:49 -0700 Subject: [PATCH 305/402] Fix broken CI; make changes in response to the comments --- lib/compress/huf_compress.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 8f96484211f..28762800c18 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -296,16 +296,18 @@ typedef struct { typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; +#define RANK_POSITION_TABLE_SIZE 32 + typedef struct { - rankPos rankPosition[32]; huffNodeTable huffNodeTbl; + rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; } HUF_buildCTable_wksp_tables; static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) { U32 n; - memset(rankPosition, 0, sizeof(*rankPosition)); + memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); for (n=0; n<=maxSymbolValue; n++) { U32 r = BIT_highbit32(count[n] + 1); rankPosition[r].base ++; @@ -328,7 +330,7 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu /** HUF_buildCTable_wksp() : * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned. + * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables). */ #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) @@ -411,8 +413,8 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo */ size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) { - U32 workspace[HUF_WORKSPACE_SIZE_U32]; - return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, workspace, sizeof(workspace)); + HUF_buildCTable_wksp_tables workspace; + return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); } size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) @@ -619,7 +621,7 @@ static size_t HUF_compressCTable_internal( typedef struct { unsigned count[HUF_SYMBOLVALUE_MAX + 1]; HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1]; - huffNodeTable nodeTable; + HUF_buildCTable_wksp_tables buildCTable_wksp; } HUF_compress_tables_t; /* HUF_compress_internal() : @@ -638,6 +640,8 @@ HUF_compress_internal (void* dst, size_t dstSize, BYTE* const oend = ostart + dstSize; BYTE* op = ostart; + HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE); + /* checks & inits */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall); @@ -679,7 +683,7 @@ HUF_compress_internal (void* dst, size_t dstSize, huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, maxSymbolValue, huffLog, - table->nodeTable, ((BYTE*)workSpace) + wkspSize - (BYTE*)table->nodeTable); + &table->buildCTable_wksp, sizeof(table->buildCTable_wksp)); CHECK_F(maxBits); huffLog = (U32)maxBits; /* Zero unused symbols in CTable, so we can check it for validity */ From e103d7b4a64c6321bb3ac4df07899ea09c3edbb2 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 1 May 2020 16:11:47 -0700 Subject: [PATCH 306/402] Fix superblock mode (#2100) Fixes: Enable RLE blocks for superblock mode Fix the limitation that the literals block must shrink. Instead, when we're within 200 bytes of the next header byte size, we will just use the next one up. That way we should (almost?) always have space for the table. Remove the limitation that the first sub-block MUST have compressed literals and be compressed. Now one sub-block MUST be compressed (otherwise we fall back to raw block which is okay, since that is streamable). If no block has compressed literals that is okay, we will fix up the next Huffman table. Handle the case where the last sub-block is uncompressed (maybe it is very small). Before it would skip superblock in this case, now we allow the last sub-block to be uncompressed. To do this we need to regenerate the correct repcodes. Respect disableLiteralsCompression in superblock mode Fix superblock mode to handle a block consisting of only compressed literals Fix a off by 1 error in superblock mode that disabled it whenever there were last literals Fix superblock mode with long literals/matches (> 0xFFFF) Allow superblock mode to repeat Huffman tables Respect ZSTD_minGain(). Tests: Simple check for the condition in #2096. When the simple_round_trip fuzzer enables superblock mode, it checks that the compressed size isn't expanded too much. Remaining limitations: O(targetCBlockSize^2) because we recompute statistics every sequence Unable to split literals of length > targetCBlockSize into multiple sequences Refuses to generate sub-blocks that don't shrink the compressed data, so we could end up with large sub-blocks. We should emit those sections as uncompressed blocks instead. ... Fixes #2096 --- lib/common/huf.h | 1 + lib/common/zstd_internal.h | 25 ++ lib/compress/huf_compress.c | 2 +- lib/compress/zstd_compress.c | 52 +++-- lib/compress/zstd_compress_internal.h | 50 ++++ lib/compress/zstd_compress_literals.c | 8 +- lib/compress/zstd_compress_superblock.c | 289 +++++++++++++++++------- lib/compress/zstd_compress_superblock.h | 1 + lib/compress/zstd_opt.c | 24 -- tests/fuzz/simple_round_trip.c | 26 ++- tests/fuzzer.c | 34 ++- 11 files changed, 378 insertions(+), 134 deletions(-) diff --git a/lib/common/huf.h b/lib/common/huf.h index 0d27ccdba94..23e184d4031 100644 --- a/lib/common/huf.h +++ b/lib/common/huf.h @@ -189,6 +189,7 @@ size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSym size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); typedef enum { HUF_repeat_none, /**< Cannot use the previous table */ diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 2103ef8594e..950b789cf44 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -291,6 +291,31 @@ typedef struct { U32 longLengthPos; } seqStore_t; +typedef struct { + U32 litLength; + U32 matchLength; +} ZSTD_sequenceLength; + +/** + * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences + * indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength. + */ +MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) +{ + ZSTD_sequenceLength seqLen; + seqLen.litLength = seq->litLength; + seqLen.matchLength = seq->matchLength + MINMATCH; + if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { + if (seqStore->longLengthID == 1) { + seqLen.litLength += 0xFFFF; + } + if (seqStore->longLengthID == 2) { + seqLen.matchLength += 0xFFFF; + } + } + return seqLen; +} + /** * Contains the compressed frame size and an upper-bound for the decompressed frame size. * Note: before using `compressedSize`, check for errors using ZSTD_isError(). diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 5cab31d042f..f54123c563e 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -417,7 +417,7 @@ size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, return nbBits >> 3; } -static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { int bad = 0; int s; for (s = 0; s <= (int)maxSymbolValue; ++s) { diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 552ca9fb44d..d12a1e6f885 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1928,21 +1928,6 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr) mlCodeTable[seqStorePtr->longLengthPos] = MaxML; } -static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams) -{ - switch (cctxParams->literalCompressionMode) { - case ZSTD_lcm_huffman: - return 0; - case ZSTD_lcm_uncompressed: - return 1; - default: - assert(0 /* impossible: pre-validated */); - /* fall-through */ - case ZSTD_lcm_auto: - return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0); - } -} - /* ZSTD_useTargetCBlockSize(): * Returns if target compressed block size param is being used. * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize. @@ -2387,6 +2372,18 @@ static int ZSTD_isRLE(const BYTE *ip, size_t length) { return 1; } +/* Returns true if the given block may be RLE. + * This is just a heuristic based on the compressibility. + * It may return both false positives and false negatives. + */ +static int ZSTD_maybeRLE(seqStore_t const* seqStore) +{ + size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); + size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart); + + return nbSeqs < 4 && nbLits < 10; +} + static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) { ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; @@ -2463,6 +2460,16 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, { DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()"); if (bss == ZSTDbss_compress) { + if (/* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + !zc->isFirstBlock && + ZSTD_maybeRLE(&zc->seqStore) && + ZSTD_isRLE((BYTE const*)src, srcSize)) + { + return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock); + } /* Attempt superblock compression. * * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the @@ -2481,12 +2488,15 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, * * cSize >= blockBound(srcSize): We have expanded the block too much so * emit an uncompressed block. */ - size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, lastBlock); - if (cSize != ERROR(dstSize_tooSmall)) { - FORWARD_IF_ERROR(cSize); - if (cSize != 0 && cSize < srcSize + ZSTD_blockHeaderSize) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; + { + size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock); + if (cSize != ERROR(dstSize_tooSmall)) { + size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy); + FORWARD_IF_ERROR(cSize); + if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) { + ZSTD_confirmRepcodesAndEntropyTables(zc); + return cSize; + } } } } diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 893e8def209..db7b89cebbd 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -326,6 +326,31 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase) return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase]; } +typedef struct repcodes_s { + U32 rep[3]; +} repcodes_t; + +MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0) +{ + repcodes_t newReps; + if (offset >= ZSTD_REP_NUM) { /* full offset */ + newReps.rep[2] = rep[1]; + newReps.rep[1] = rep[0]; + newReps.rep[0] = offset - ZSTD_REP_MOVE; + } else { /* repcode */ + U32 const repCode = offset + ll0; + if (repCode > 0) { /* note : if repCode==0, no change */ + U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; + newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2]; + newReps.rep[1] = rep[0]; + newReps.rep[0] = currentOffset; + } else { /* repCode == 0 */ + memcpy(&newReps, rep, sizeof(newReps)); + } + } + return newReps; +} + /* ZSTD_cParam_withinBounds: * @return 1 if value is within cParam bounds, * 0 otherwise */ @@ -351,6 +376,16 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi return ZSTD_blockHeaderSize + srcSize; } +MEM_STATIC size_t ZSTD_rleCompressBlock (void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock) +{ + BYTE* const op = (BYTE*)dst; + U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3); + RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, ""); + MEM_writeLE24(op, cBlockHeader); + op[3] = src; + return 4; +} + /* ZSTD_minGain() : * minimum compression required @@ -364,6 +399,21 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat) return (srcSize >> minlog) + 2; } +MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams) +{ + switch (cctxParams->literalCompressionMode) { + case ZSTD_lcm_huffman: + return 0; + case ZSTD_lcm_uncompressed: + return 1; + default: + assert(0 /* impossible: pre-validated */); + /* fall-through */ + case ZSTD_lcm_auto: + return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0); + } +} + /*! ZSTD_safecopyLiterals() : * memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w. * Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c index 8d22bcadffb..b7680004606 100644 --- a/lib/compress/zstd_compress_literals.c +++ b/lib/compress/zstd_compress_literals.c @@ -36,6 +36,7 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, } memcpy(ostart + flSize, src, srcSize); + DEBUGLOG(5, "Raw literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize)); return srcSize + flSize; } @@ -62,6 +63,7 @@ size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* } ostart[flSize] = *(const BYTE*)src; + DEBUGLOG(5, "RLE literals: %u -> %u", (U32)srcSize, (U32)flSize + 1); return flSize+1; } @@ -80,8 +82,8 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, symbolEncodingType_e hType = set_compressed; size_t cLitSize; - DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)", - disableLiteralCompression); + DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i srcSize=%u)", + disableLiteralCompression, (U32)srcSize); /* Prepare nextEntropy assuming reusing the existing table */ memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); @@ -110,6 +112,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2); if (repeat != HUF_repeat_none) { /* reused the existing table */ + DEBUGLOG(5, "Reusing previous huffman table"); hType = set_repeat; } } @@ -150,5 +153,6 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, default: /* not possible : lhSize is {3,4,5} */ assert(0); } + DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)srcSize, (U32)(lhSize+cLitSize)); return lhSize+cLitSize; } diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 8c98d18e151..fd475dcc243 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -16,6 +16,7 @@ #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" #include "zstd_compress_superblock.h" +#include "zstd_internal.h" /* ZSTD_getSequenceLength */ /*-************************************* * Superblock entropy buffer structs @@ -53,15 +54,14 @@ typedef struct { /** ZSTD_buildSuperBlockEntropy_literal() : * Builds entropy for the super-block literals. - * Stores literals block type (raw, rle, compressed) and + * Stores literals block type (raw, rle, compressed, repeat) and * huffman description table to hufMetadata. - * Currently, this does not consider the option of reusing huffman table from - * previous super-block. I think it would be a good improvement to add that option. * @return : size of huffman description table or error code */ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize, const ZSTD_hufCTables_t* prevHuf, ZSTD_hufCTables_t* nextHuf, ZSTD_hufCTablesMetadata_t* hufMetadata, + const int disableLiteralsCompression, void* workspace, size_t wkspSize) { BYTE* const wkspStart = (BYTE*)workspace; @@ -72,26 +72,49 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz BYTE* const nodeWksp = countWkspStart + countWkspSize; const size_t nodeWkspSize = wkspEnd-nodeWksp; unsigned maxSymbolValue = 255; - unsigned huffLog = 11; + unsigned huffLog = HUF_TABLELOG_DEFAULT; + HUF_repeat repeat = prevHuf->repeatMode; DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize); /* Prepare nextEntropy assuming reusing the existing table */ memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + if (disableLiteralsCompression) { + DEBUGLOG(5, "set_basic - disabled"); + hufMetadata->hType = set_basic; + return 0; + } + /* small ? don't even attempt compression (speed opt) */ # define COMPRESS_LITERALS_SIZE_MIN 63 - { size_t const minLitSize = COMPRESS_LITERALS_SIZE_MIN; - if (srcSize <= minLitSize) { hufMetadata->hType = set_basic; return 0; } + { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; + if (srcSize <= minLitSize) { + DEBUGLOG(5, "set_basic - too small"); + hufMetadata->hType = set_basic; + return 0; + } } /* Scan input and build symbol stats */ { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize); FORWARD_IF_ERROR(largest); - if (largest == srcSize) { hufMetadata->hType = set_rle; return 0; } - if (largest <= (srcSize >> 7)+4) { hufMetadata->hType = set_basic; return 0; } + if (largest == srcSize) { + DEBUGLOG(5, "set_rle"); + hufMetadata->hType = set_rle; + return 0; + } + if (largest <= (srcSize >> 7)+4) { + DEBUGLOG(5, "set_basic - no gain"); + hufMetadata->hType = set_basic; + return 0; + } } + /* Validate the previous Huffman table */ + if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) { + repeat = HUF_repeat_none; + } /* Build Huffman Tree */ memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); @@ -101,13 +124,32 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz nodeWksp, nodeWkspSize); FORWARD_IF_ERROR(maxBits); huffLog = (U32)maxBits; - { size_t cSize = HUF_estimateCompressedSize( - (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); - size_t hSize = HUF_writeCTable( - hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), - (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog); - if (cSize + hSize >= srcSize) { hufMetadata->hType = set_basic; return 0; } + { /* Build and write the CTable */ + size_t const newCSize = HUF_estimateCompressedSize( + (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); + size_t const hSize = HUF_writeCTable( + hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), + (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog); + /* Check against repeating the previous CTable */ + if (repeat != HUF_repeat_none) { + size_t const oldCSize = HUF_estimateCompressedSize( + (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); + if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { + DEBUGLOG(5, "set_repeat - smaller"); + memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_repeat; + return 0; + } + } + if (newCSize + hSize >= srcSize) { + DEBUGLOG(5, "set_basic - no gains"); + memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_basic; + return 0; + } + DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize); hufMetadata->hType = set_compressed; + nextHuf->repeatMode = HUF_repeat_check; return hSize; } } @@ -241,6 +283,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize, &prevEntropy->huf, &nextEntropy->huf, &entropyMetadata->hufMetadata, + ZSTD_disableLiteralsCompression(cctxParams), workspace, wkspSize); FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize); entropyMetadata->fseMetadata.fseTablesSize = @@ -255,21 +298,19 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, /** ZSTD_compressSubBlock_literal() : * Compresses literals section for a sub-block. - * Compressed literal size needs to be less than uncompressed literal size. - * ZSTD spec doesn't have this constaint. I will explain why I have this constraint here. - * Literals section header size ranges from 1 to 5 bytes, - * which is dictated by regenerated size and compressed size. - * In order to figure out the memory address to start writing compressed literal, - * it is necessary to figure out the literals section header size. - * The challenge is that compressed size is only known after compression. - * This is a chicken and egg problem. - * I am simplifying the problem by assuming that - * compressed size will always be less than or equal to regenerated size, - * and using regenerated size to calculate literals section header size. + * When we have to write the Huffman table we will sometimes choose a header + * size larger than necessary. This is because we have to pick the header size + * before we know the table size + compressed size, so we have a bound on the + * table size. If we guessed incorrectly, we fall back to uncompressed literals. + * + * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded + * in writing the header, otherwise it is set to 0. + * * hufMetadata->hType has literals block type info. * If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block. * If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block. * If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block + * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block * and the following sub-blocks' literals sections will be Treeless_Literals_Block. * @return : compressed size of literals section of a sub-block * Or 0 if it unable to compress. @@ -278,28 +319,22 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, const ZSTD_hufCTablesMetadata_t* hufMetadata, const BYTE* literals, size_t litSize, void* dst, size_t dstSize, - const int bmi2, int writeEntropy) + const int bmi2, int writeEntropy, int* entropyWritten) { - size_t const lhSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB); + size_t const header = writeEntropy ? 200 : 0; + size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header)); BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstSize; BYTE* op = ostart + lhSize; - U32 singleStream = litSize < 256; - symbolEncodingType_e hType = writeEntropy ? set_compressed : set_repeat; + U32 const singleStream = lhSize == 3; + symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; size_t cLitSize = 0; (void)bmi2; // TODO bmi2... DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy); - if (writeEntropy && litSize == 0) { - /* Literals section cannot be compressed mode when litSize == 0. - * (This seems to be decoder constraint.) - * Entropy cannot be written if literals section is not compressed mode. - */ - return 0; - } - + *entropyWritten = 0; if (litSize == 0 || hufMetadata->hType == set_basic) { DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal"); return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); @@ -308,8 +343,10 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize); } - if (lhSize == 3) singleStream = 1; - if (writeEntropy) { + assert(litSize > 0); + assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat); + + if (writeEntropy && hufMetadata->hType == set_compressed) { memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); op += hufMetadata->hufDesSize; cLitSize += hufMetadata->hufDesSize; @@ -322,11 +359,19 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, op += cSize; cLitSize += cSize; if (cSize == 0 || ERR_isError(cSize)) { - return 0; + DEBUGLOG(5, "Failed to write entropy tables %s", ZSTD_getErrorName(cSize)); + return 0; + } + /* If we expand and we aren't writing a header then emit uncompressed */ + if (!writeEntropy && cLitSize >= litSize) { + DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal because uncompressible"); + return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); } - if (cLitSize > litSize) { - if (writeEntropy) return 0; - else return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); + /* If we are writing headers then allow expansion that doesn't change our header size. */ + if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) { + assert(cLitSize > litSize); + DEBUGLOG(5, "Literals expanded beyond allowed header size"); + return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); } DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize); } @@ -353,17 +398,26 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, default: /* not possible : lhSize is {3,4,5} */ assert(0); } + *entropyWritten = 1; + DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart)); return op-ostart; } -static size_t ZSTD_seqDecompressedSize(const seqDef* sequences, size_t nbSeq, size_t litSize) { +static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef* sequences, size_t nbSeq, size_t litSize, int lastSequence) { const seqDef* const sstart = sequences; const seqDef* const send = sequences + nbSeq; const seqDef* sp = sstart; size_t matchLengthSum = 0; + size_t litLengthSum = 0; while (send-sp > 0) { - matchLengthSum += sp->matchLength + MINMATCH; - sp++; + ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp); + litLengthSum += seqLen.litLength; + matchLengthSum += seqLen.matchLength; + sp++; + } + assert(litLengthSum <= litSize); + if (!lastSequence) { + assert(litLengthSum == litSize); } return matchLengthSum + litSize; } @@ -372,8 +426,9 @@ static size_t ZSTD_seqDecompressedSize(const seqDef* sequences, size_t nbSeq, si * Compresses sequences section for a sub-block. * fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have * symbol compression modes for the super-block. - * First sub-block will have these in its header. The following sub-blocks - * will always have repeat mode. + * The first successfully compressed block will have these in its header. + * We set entropyWritten=1 when we succeed in compressing the sequences. + * The following sub-blocks will always have repeat mode. * @return : compressed size of sequences section of a sub-block * Or 0 if it is unable to compress * Or error code. */ @@ -383,7 +438,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, const ZSTD_CCtx_params* cctxParams, void* dst, size_t dstCapacity, - const int bmi2, int writeEntropy) + const int bmi2, int writeEntropy, int* entropyWritten) { const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; BYTE* const ostart = (BYTE*)dst; @@ -393,6 +448,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets); + *entropyWritten = 0; /* Sequences Header */ RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, dstSize_tooSmall); @@ -402,9 +458,6 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; - if (writeEntropy && nbSeq == 0) { - return 0; - } if (nbSeq==0) { return op - ostart; } @@ -444,6 +497,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables * In this exceedingly rare case, we will simply emit an uncompressed * block, since it isn't worth optimizing. */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) { /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ assert(fseMetadata->lastCountSize + bitstreamSize == 3); @@ -451,6 +505,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables "emitting an uncompressed block."); return 0; } +#endif DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize); } @@ -461,10 +516,15 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables * with rle mode and the current block's sequences section is compressed * with repeat mode where sequences section body size can be 1 byte. */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (op-seqHead < 4) { + DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting " + "an uncompressed block when sequences are < 4 bytes"); return 0; } +#endif + *entropyWritten = 1; return op - ostart; } @@ -479,16 +539,19 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, const ZSTD_CCtx_params* cctxParams, void* dst, size_t dstCapacity, - const int bmi2, int writeEntropy, U32 lastBlock) + const int bmi2, + int writeLitEntropy, int writeSeqEntropy, + int* litEntropyWritten, int* seqEntropyWritten, + U32 lastBlock) { BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstCapacity; BYTE* op = ostart + ZSTD_blockHeaderSize; - DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeEntropy=%d, lastBlock=%d)", - litSize, nbSeq, writeEntropy, lastBlock); + DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)", + litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock); { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable, &entropyMetadata->hufMetadata, literals, litSize, - op, oend-op, bmi2, writeEntropy); + op, oend-op, bmi2, writeLitEntropy, litEntropyWritten); FORWARD_IF_ERROR(cLitSize); if (cLitSize == 0) return 0; op += cLitSize; @@ -499,7 +562,7 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, llCode, mlCode, ofCode, cctxParams, op, oend-op, - bmi2, writeEntropy); + bmi2, writeSeqEntropy, seqEntropyWritten); FORWARD_IF_ERROR(cSeqSize); if (cSeqSize == 0) return 0; op += cSeqSize; @@ -524,7 +587,7 @@ static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t lit if (hufMetadata->hType == set_basic) return litSize; else if (hufMetadata->hType == set_rle) return 1; - else if (hufMetadata->hType == set_compressed) { + else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize); if (ZSTD_isError(largest)) return litSize; { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue); @@ -601,17 +664,28 @@ static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize, const ZSTD_entropyCTables_t* entropy, const ZSTD_entropyCTablesMetadata_t* entropyMetadata, void* workspace, size_t wkspSize, - int writeEntropy) { + int writeLitEntropy, int writeSeqEntropy) { size_t cSizeEstimate = 0; cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize, &entropy->huf, &entropyMetadata->hufMetadata, - workspace, wkspSize, writeEntropy); + workspace, wkspSize, writeLitEntropy); cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable, nbSeq, &entropy->fse, &entropyMetadata->fseMetadata, - workspace, wkspSize, writeEntropy); + workspace, wkspSize, writeSeqEntropy); return cSizeEstimate + ZSTD_blockHeaderSize; } +static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata) +{ + if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle) + return 1; + if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle) + return 1; + if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle) + return 1; + return 0; +} + /** ZSTD_compressSubBlock_multi() : * Breaks super-block into multiple sub-blocks and compresses them. * Entropy will be written to the first block. @@ -620,10 +694,12 @@ static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize, * @return : compressed size of the super block (which is multiple ZSTD blocks) * Or 0 if it failed to compress. */ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, - const ZSTD_entropyCTables_t* entropy, + const ZSTD_compressedBlockState_t* prevCBlock, + ZSTD_compressedBlockState_t* nextCBlock, const ZSTD_entropyCTablesMetadata_t* entropyMetadata, const ZSTD_CCtx_params* cctxParams, void* dst, size_t dstCapacity, + const void* src, size_t srcSize, const int bmi2, U32 lastBlock, void* workspace, size_t wkspSize) { @@ -633,6 +709,8 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, const BYTE* const lstart = seqStorePtr->litStart; const BYTE* const lend = seqStorePtr->lit; const BYTE* lp = lstart; + BYTE const* ip = (BYTE const*)src; + BYTE const* const iend = ip + srcSize; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstCapacity; BYTE* op = ostart; @@ -641,41 +719,57 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, const BYTE* ofCodePtr = seqStorePtr->ofCode; size_t targetCBlockSize = cctxParams->targetCBlockSize; size_t litSize, seqCount; - int writeEntropy = 1; - size_t remaining = ZSTD_seqDecompressedSize(sstart, send-sstart, lend-lstart); - size_t cBlockSizeEstimate = 0; + int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed; + int writeSeqEntropy = 1; + int lastSequence = 0; DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)", (unsigned)(lend-lp), (unsigned)(send-sstart)); litSize = 0; seqCount = 0; - while (sp + seqCount < send) { - const seqDef* const sequence = sp + seqCount; - const U32 lastSequence = sequence+1 == send; - litSize = (sequence == send) ? (size_t)(lend-lp) : litSize + sequence->litLength; - seqCount++; + do { + size_t cBlockSizeEstimate = 0; + if (sstart == send) { + lastSequence = 1; + } else { + const seqDef* const sequence = sp + seqCount; + lastSequence = sequence == send - 1; + litSize += ZSTD_getSequenceLength(seqStorePtr, sequence).litLength; + seqCount++; + } + if (lastSequence) { + assert(lp <= lend); + assert(litSize <= (size_t)(lend - lp)); + litSize = (size_t)(lend - lp); + } /* I think there is an optimization opportunity here. * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful * since it recalculates estimate from scratch. * For example, it would recount literal distribution and symbol codes everytime. */ cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount, - entropy, entropyMetadata, - workspace, wkspSize, writeEntropy); + &nextCBlock->entropy, entropyMetadata, + workspace, wkspSize, writeLitEntropy, writeSeqEntropy); if (cBlockSizeEstimate > targetCBlockSize || lastSequence) { - const size_t decompressedSize = ZSTD_seqDecompressedSize(sp, seqCount, litSize); - const size_t cSize = ZSTD_compressSubBlock(entropy, entropyMetadata, + int litEntropyWritten = 0; + int seqEntropyWritten = 0; + const size_t decompressedSize = ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSequence); + const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata, sp, seqCount, lp, litSize, llCodePtr, mlCodePtr, ofCodePtr, cctxParams, op, oend-op, - bmi2, writeEntropy, lastBlock && lastSequence); + bmi2, writeLitEntropy, writeSeqEntropy, + &litEntropyWritten, &seqEntropyWritten, + lastBlock && lastSequence); FORWARD_IF_ERROR(cSize); + DEBUGLOG(5, "cSize = %zu | decompressedSize = %zu", cSize, decompressedSize); if (cSize > 0 && cSize < decompressedSize) { - assert(remaining >= decompressedSize); - remaining -= decompressedSize; + DEBUGLOG(5, "Committed the sub-block"); + assert(ip + decompressedSize <= iend); + ip += decompressedSize; sp += seqCount; lp += litSize; op += cSize; @@ -684,20 +778,51 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, ofCodePtr += seqCount; litSize = 0; seqCount = 0; - writeEntropy = 0; // Entropy only needs to be written once + /* Entropy only needs to be written once */ + if (litEntropyWritten) { + writeLitEntropy = 0; + } + if (seqEntropyWritten) { + writeSeqEntropy = 0; + } } } + } while (!lastSequence); + if (writeLitEntropy) { + DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten"); + memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); } - if (remaining) { - DEBUGLOG(5, "ZSTD_compressSubBlock_multi failed to compress"); + if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) { + /* If we haven't written our entropy tables, then we've violated our contract and + * must emit an uncompressed block. + */ + DEBUGLOG(5, "ZSTD_compressSubBlock_multi has sequence entropy tables unwritten"); return 0; } + if (ip < iend) { + size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock); + DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip)); + FORWARD_IF_ERROR(cSize); + assert(cSize != 0); + op += cSize; + /* We have to regenerate the repcodes because we've skipped some sequences */ + if (sp < send) { + seqDef const* seq; + repcodes_t rep; + memcpy(&rep, prevCBlock->rep, sizeof(rep)); + for (seq = sstart; seq < sp; ++seq) { + rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); + } + memcpy(nextCBlock->rep, &rep, sizeof(rep)); + } + } DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed"); return op-ostart; } size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, + void const* src, size_t srcSize, unsigned lastBlock) { ZSTD_entropyCTablesMetadata_t entropyMetadata; @@ -709,10 +834,12 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */)); return ZSTD_compressSubBlock_multi(&zc->seqStore, - &zc->blockState.nextCBlock->entropy, + zc->blockState.prevCBlock, + zc->blockState.nextCBlock, &entropyMetadata, &zc->appliedParams, dst, dstCapacity, + src, srcSize, zc->bmi2, lastBlock, zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */); } diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h index 3bd6fdcf33e..35d207299d8 100644 --- a/lib/compress/zstd_compress_superblock.h +++ b/lib/compress/zstd_compress_superblock.h @@ -26,6 +26,7 @@ * The given block will be compressed into multiple sub blocks that are around targetCBlockSize. */ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, + void const* src, size_t srcSize, unsigned lastBlock); #endif /* ZSTD_COMPRESS_ADVANCED_H */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index a835e9ec285..8d63019654e 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -765,30 +765,6 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( /*-******************************* * Optimal parser *********************************/ -typedef struct repcodes_s { - U32 rep[3]; -} repcodes_t; - -static repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0) -{ - repcodes_t newReps; - if (offset >= ZSTD_REP_NUM) { /* full offset */ - newReps.rep[2] = rep[1]; - newReps.rep[1] = rep[0]; - newReps.rep[0] = offset - ZSTD_REP_MOVE; - } else { /* repcode */ - U32 const repCode = offset + ll0; - if (repCode > 0) { /* note : if repCode==0, no change */ - U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2]; - newReps.rep[1] = rep[0]; - newReps.rep[0] = currentOffset; - } else { /* repCode == 0 */ - memcpy(&newReps, rep, sizeof(newReps)); - } - } - return newReps; -} static U32 ZSTD_totalLen(ZSTD_optimal_t sol) diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c index e37fa6f6f61..41ea96739fe 100644 --- a/tests/fuzz/simple_round_trip.c +++ b/tests/fuzz/simple_round_trip.c @@ -32,9 +32,12 @@ static size_t roundTripTest(void *result, size_t resultCapacity, FUZZ_dataProducer_t *producer) { size_t cSize; + size_t dSize; + int targetCBlockSize = 0; if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) { FUZZ_setRandomParameters(cctx, srcSize, producer); cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize); + FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_targetCBlockSize, &targetCBlockSize)); } else { int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel); @@ -42,14 +45,33 @@ static size_t roundTripTest(void *result, size_t resultCapacity, cctx, compressed, compressedCapacity, src, srcSize, cLevel); } FUZZ_ZASSERT(cSize); - return ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize); + dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize); + FUZZ_ZASSERT(dSize); + /* When superblock is enabled make sure we don't expand the block more than expected. */ + if (targetCBlockSize != 0) { + size_t normalCSize; + FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 0)); + normalCSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize); + FUZZ_ZASSERT(normalCSize); + { + size_t const bytesPerBlock = 3 /* block header */ + + 5 /* Literal header */ + + 6 /* Huffman jump table */ + + 3 /* number of sequences */ + + 1 /* symbol compression modes */; + size_t const expectedExpansion = bytesPerBlock * (1 + (normalCSize / MAX(1, targetCBlockSize))); + size_t const allowedExpansion = (srcSize >> 4) + 3 * expectedExpansion + 10; + FUZZ_ASSERT(cSize <= normalCSize + allowedExpansion); + } + } + return dSize; } int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { size_t const rBufSize = size; void* rBuf = malloc(rBufSize); - size_t cBufSize = ZSTD_compressBound(size) * 2; + size_t cBufSize = ZSTD_compressBound(size); void* cBuf; /* Give a random portion of src data to the producer, to use for diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 416df24d2a1..700cb577160 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -708,8 +708,8 @@ static int basicUnitTests(U32 const seed, double compressibility) for (read = 0; read < streamCompressThreshold; read += streamCompressDelta) { ZSTD_inBuffer in = {src, streamCompressDelta, 0}; ZSTD_outBuffer out = {dst, dstCapacity, 0}; - assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue))); - assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end))); + CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue)); + CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)); src += streamCompressDelta; srcSize -= streamCompressDelta; dst += out.pos; dstCapacity -= out.pos;}} @@ -717,7 +717,35 @@ static int basicUnitTests(U32 const seed, double compressibility) { ZSTD_inBuffer in = {src, srcSize, 0}; ZSTD_outBuffer out = {dst, dstCapacity, 0}; - assert(!ZSTD_isError(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end)));} + CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));} + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3d: superblock with no literals : ", testNb++); + /* Generate the same data 20 times over */ + { + size_t const avgChunkSize = CNBuffSize / 20; + size_t b; + for (b = 0; b < CNBuffSize; b += avgChunkSize) { + size_t const chunkSize = MIN(CNBuffSize - b, avgChunkSize); + RDG_genBuffer((char*)CNBuffer + b, chunkSize, compressibility, 0. /* auto */, seed); + } + } + { + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + size_t const normalCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); + size_t const allowedExpansion = (CNBuffSize * 3 / 1000); + size_t superCSize; + CHECK_Z(normalCSize); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19); + ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetCBlockSize, 1000); + superCSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize); + CHECK_Z(superCSize); + if (superCSize > normalCSize + allowedExpansion) { + DISPLAYLEVEL(1, "Superblock too big: %u > %u + %u \n", (U32)superCSize, (U32)normalCSize, (U32)allowedExpansion); + goto _output_error; + } ZSTD_freeCCtx(cctx); } DISPLAYLEVEL(3, "OK \n"); From 5e5f262612dd4de99e9b116a5bcb3d145d061616 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 12:24:56 -0400 Subject: [PATCH 307/402] Add (Possibly Empty) Info Strings to All Variadic Error Handling Macro Invocations --- lib/compress/zstd_compress.c | 267 +++++++++++++----------- lib/compress/zstd_compress_internal.h | 2 +- lib/compress/zstd_compress_literals.c | 2 +- lib/compress/zstd_compress_sequences.c | 16 +- lib/compress/zstd_compress_superblock.c | 27 ++- lib/compress/zstd_cwksp.h | 2 +- lib/compress/zstdmt_compress.c | 12 +- lib/decompress/zstd_ddict.c | 4 +- lib/decompress/zstd_decompress.c | 160 +++++++------- lib/decompress/zstd_decompress_block.c | 66 +++--- 10 files changed, 285 insertions(+), 273 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index d12a1e6f885..a2ef61aee3a 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -235,7 +235,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params) } size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { - RETURN_ERROR_IF(!cctxParams, GENERIC); + RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); memset(cctxParams, 0, sizeof(*cctxParams)); cctxParams->compressionLevel = compressionLevel; cctxParams->fParams.contentSizeFlag = 1; @@ -244,8 +244,8 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) { - RETURN_ERROR_IF(!cctxParams, GENERIC); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) ); + RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); memset(cctxParams, 0, sizeof(*cctxParams)); assert(!ZSTD_checkCParams(params.cParams)); cctxParams->cParams = params.cParams; @@ -441,7 +441,7 @@ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value) #define BOUNDCHECK(cParam, val) { \ RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \ - parameter_outOfBound); \ + parameter_outOfBound, "Param out of bounds"); \ } @@ -489,7 +489,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) if (ZSTD_isUpdateAuthorized(param)) { cctx->cParamsChanged = 1; } else { - RETURN_ERROR(stage_wrong); + RETURN_ERROR(stage_wrong, "can only set params in ctx init stage"); } } switch(param) @@ -526,7 +526,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_srcSizeHint: break; - default: RETURN_ERROR(parameter_unsupported); + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value); } @@ -543,7 +543,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, return (size_t)CCtxParams->format; case ZSTD_c_compressionLevel : { - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value)); + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); if (value) { /* 0 : does not change current level */ CCtxParams->compressionLevel = value; } @@ -631,7 +631,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); return 0; #else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value)); + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); CCtxParams->nbWorkers = value; return CCtxParams->nbWorkers; #endif @@ -644,7 +644,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, /* Adjust to the minimum non-default value. */ if (value != 0 && value < ZSTDMT_JOBSIZE_MIN) value = ZSTDMT_JOBSIZE_MIN; - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value)); + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); assert(value >= 0); CCtxParams->jobSize = value; return CCtxParams->jobSize; @@ -655,7 +655,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); return 0; #else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value)); + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); CCtxParams->overlapLog = value; return CCtxParams->overlapLog; #endif @@ -665,7 +665,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); return 0; #else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value)); + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); CCtxParams->rsyncable = value; return CCtxParams->rsyncable; #endif @@ -694,7 +694,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_ldmHashRateLog : RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN, - parameter_outOfBound); + parameter_outOfBound, "Param out of bounds!"); CCtxParams->ldmParams.hashRateLog = value; return CCtxParams->ldmParams.hashRateLog; @@ -834,8 +834,11 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams( ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) { DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams"); - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); - RETURN_ERROR_IF(cctx->cdict, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "The context is in the wrong stage!"); + RETURN_ERROR_IF(cctx->cdict, stage_wrong, + "Can't override parameters with cdict attached (some must " + "be inherited from the cdict)."); cctx->requestedParams = *params; return 0; @@ -844,7 +847,8 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams( ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize) { DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize); - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't set pledgedSrcSize when not in init stage."); cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; return 0; } @@ -882,7 +886,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) dl->dictContentType, cParams, cctx->customMem); - RETURN_ERROR_IF(!dl->cdict, memory_allocation); + RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed"); cctx->cdict = dl->cdict; return 0; } @@ -891,7 +895,8 @@ size_t ZSTD_CCtx_loadDictionary_advanced( ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType) { - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't load a dictionary when ctx is not in init stage."); RETURN_ERROR_IF(cctx->staticSize, memory_allocation, "no malloc for static CCtx"); DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); @@ -902,7 +907,7 @@ size_t ZSTD_CCtx_loadDictionary_advanced( cctx->localDict.dict = dict; } else { void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem); - RETURN_ERROR_IF(!dictBuffer, memory_allocation); + RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!"); memcpy(dictBuffer, dict, dictSize); cctx->localDict.dictBuffer = dictBuffer; cctx->localDict.dict = dictBuffer; @@ -928,7 +933,8 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) { - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a dict when ctx not in init stage."); /* Free the existing local cdict (if any) to save memory. */ ZSTD_clearAllDicts(cctx); cctx->cdict = cdict; @@ -943,7 +949,8 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz size_t ZSTD_CCtx_refPrefix_advanced( ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) { - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a prefix when ctx not in init stage."); ZSTD_clearAllDicts(cctx); if (prefix != NULL && prefixSize > 0) { cctx->prefixDict.dict = prefix; @@ -964,7 +971,8 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) } if ( (reset == ZSTD_reset_parameters) || (reset == ZSTD_reset_session_and_parameters) ) { - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't reset parameters only when not in init stage."); ZSTD_clearAllDicts(cctx); return ZSTD_CCtxParams_reset(&cctx->requestedParams); } @@ -1474,7 +1482,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, needsIndexReset = ZSTDirp_reset; ZSTD_cwksp_free(ws, zc->customMem); - FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem)); + FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), ""); DEBUGLOG(5, "reserving object space"); /* Statically sized space. @@ -1545,7 +1553,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ¶ms.cParams, crp, needsIndexReset, - ZSTD_resetTarget_CCtx)); + ZSTD_resetTarget_CCtx), ""); /* ldm hash table */ if (params.ldmParams.enableLdm) { @@ -1623,7 +1631,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); params.cParams.windowLog = windowLog; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, - ZSTDcrp_makeClean, zbuff)); + ZSTDcrp_makeClean, zbuff), ""); assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); } @@ -1672,7 +1680,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, params.cParams = *cdict_cParams; params.cParams.windowLog = windowLog; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, - ZSTDcrp_leaveDirty, zbuff)); + ZSTDcrp_leaveDirty, zbuff), ""); assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog); assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog); @@ -1753,7 +1761,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, ZSTD_buffered_policy_e zbuff) { DEBUGLOG(5, "ZSTD_copyCCtx_internal"); - RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong); + RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, + "Can't copy a ctx that's not in init stage."); memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); { ZSTD_CCtx_params params = dstCCtx->requestedParams; @@ -1981,14 +1990,14 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, literals, litSize, entropyWorkspace, entropyWkspSize, bmi2); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed"); assert(cSize <= dstCapacity); op += cSize; } /* Sequences Header */ RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, - dstSize_tooSmall); + dstSize_tooSmall, "Can't fit seq hdr in output buf!"); if (nbSeq < 128) { *op++ = (BYTE)nbSeq; } else if (nbSeq < LONGNBSEQ) { @@ -2033,7 +2042,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, prevEntropy->fse.litlengthCTable, sizeof(prevEntropy->fse.litlengthCTable), entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); if (LLtype == set_compressed) lastNCount = op; op += countSize; @@ -2061,7 +2070,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, prevEntropy->fse.offcodeCTable, sizeof(prevEntropy->fse.offcodeCTable), entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); if (Offtype == set_compressed) lastNCount = op; op += countSize; @@ -2087,7 +2096,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, prevEntropy->fse.matchlengthCTable, sizeof(prevEntropy->fse.matchlengthCTable), entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); if (MLtype == set_compressed) lastNCount = op; op += countSize; @@ -2103,7 +2112,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, CTable_LitLength, llCodeTable, sequences, nbSeq, longOffsets, bmi2); - FORWARD_IF_ERROR(bitstreamSize); + FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); op += bitstreamSize; assert(op <= oend); /* zstd versions <= 1.3.4 mistakenly report corruption when @@ -2147,7 +2156,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, */ if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) return 0; /* block not compressed */ - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed"); /* Check compressibility */ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); @@ -2273,7 +2282,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* Updates ldmSeqStore.size */ FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore, &zc->appliedParams.ldmParams, - src, srcSize)); + src, srcSize), ""); /* Updates ldmSeqStore.pos */ lastLLSize = ZSTD_ldm_blockCompress(&ldmSeqStore, @@ -2349,7 +2358,7 @@ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem); SeqCollector seqCollector; - RETURN_ERROR_IF(dst == NULL, memory_allocation); + RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); seqCollector.collectSequences = 1; seqCollector.seqStart = outSeqs; @@ -2408,7 +2417,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, (unsigned)zc->blockState.matchState.nextToUpdate); { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); - FORWARD_IF_ERROR(bss); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; } } @@ -2492,7 +2501,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock); if (cSize != ERROR(dstSize_tooSmall)) { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed"); if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) { ZSTD_confirmRepcodesAndEntropyTables(zc); return cSize; @@ -2517,10 +2526,10 @@ static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); - FORWARD_IF_ERROR(bss); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed"); if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; @@ -2596,18 +2605,18 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, { size_t cSize; if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) { cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed"); assert(cSize > 0); assert(cSize <= blockSize + ZSTD_blockHeaderSize); } else { cSize = ZSTD_compressBlock_internal(cctx, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, ip, blockSize, 1 /* frame */); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed"); if (cSize == 0) { /* block is not compressible */ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); } else { U32 const cBlockHeader = cSize == 1 ? lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : @@ -2649,7 +2658,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, size_t pos=0; assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)); - RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall); + RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall, + "dst buf is too small to fit worst-case frame header size."); DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); @@ -2685,7 +2695,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, */ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity) { - RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall); + RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, + "dst buf is too small to write frame trailer empty block."); { U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */ MEM_writeLE24(dst, cBlockHeader24); return ZSTD_blockHeaderSize; @@ -2694,9 +2705,11 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity) size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq) { - RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong); + RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong, + "wrong cctx stage"); RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm, - parameter_unsupported); + parameter_unsupported, + "incompatible with ldm"); cctx->externSeqStore.seq = seq; cctx->externSeqStore.size = nbSeq; cctx->externSeqStore.capacity = nbSeq; @@ -2721,7 +2734,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, if (frame && (cctx->stage==ZSTDcs_init)) { fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, cctx->pledgedSrcSizePlusOne-1, cctx->dictID); - FORWARD_IF_ERROR(fhSize); + FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); assert(fhSize <= dstCapacity); dstCapacity -= fhSize; dst = (char*)dst + fhSize; @@ -2748,7 +2761,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, { size_t const cSize = frame ? ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed"); cctx->consumedSrcSize += srcSize; cctx->producedCSize += (cSize + fhSize); assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); @@ -2785,7 +2798,7 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const { DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize); { size_t const blockSizeMax = ZSTD_getBlockSize(cctx); - RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong); } + RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); } return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); } @@ -2868,9 +2881,9 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, NOTE: This behavior is not standard and could be improved in the future. */ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { U32 s; - RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted); + RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols"); for (s = 0; s <= maxSymbolValue; ++s) { - RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted); + RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols"); } return 0; } @@ -2894,56 +2907,56 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, if (!hasZeroWeights) bs->entropy.huf.repeatMode = HUF_repeat_valid; - RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted); + RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, ""); dictPtr += hufHeaderSize; } { unsigned offcodeLog; size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ /* fill all offset symbols to avoid garbage at end of table */ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.offcodeCTable, offcodeNCount, MaxOff, offcodeLog, workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted); + dictionary_corrupted, ""); dictPtr += offcodeHeaderSize; } { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); /* Every match length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); + FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted); + dictionary_corrupted, ""); dictPtr += matchlengthHeaderSize; } { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); /* Every literal length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); + FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted); + dictionary_corrupted, ""); dictPtr += litlengthHeaderSize; } - RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted); + RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, ""); bs->rep[0] = MEM_readLE32(dictPtr+0); bs->rep[1] = MEM_readLE32(dictPtr+4); bs->rep[2] = MEM_readLE32(dictPtr+8); @@ -2982,7 +2995,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); - FORWARD_IF_ERROR(eSize); + FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed"); dictPtr += eSize; { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); @@ -2992,19 +3005,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ } /* All offset values <= dictContentSize + 128 KB must be representable */ - FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff))); + FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), ""); /* All repCodes must be <= dictContentSize and != 0*/ { U32 u; for (u=0; u<3; u++) { - RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted); - RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted); + RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); + RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); } } bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( - ms, NULL, ws, params, dictPtr, dictContentSize, dtlm)); + ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), ""); return dictID; } } @@ -3024,7 +3037,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, { DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize); if ((dict==NULL) || (dictSize<8)) { - RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong); + RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); return 0; } @@ -3040,7 +3053,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, return ZSTD_loadDictionaryContent( ms, ls, ws, params, dict, dictSize, dtlm); } - RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong); + RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); assert(0); /* impossible */ } @@ -3077,7 +3090,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, } FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize, - ZSTDcrp_makeClean, zbuff) ); + ZSTDcrp_makeClean, zbuff) , ""); { size_t const dictID = cdict ? ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, @@ -3088,7 +3101,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, dictContentType, dtlm, cctx->entropyWorkspace); - FORWARD_IF_ERROR(dictID); + FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); assert(dictID <= UINT_MAX); cctx->dictID = (U32)dictID; } @@ -3105,7 +3118,7 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, { DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog); /* compression parameters verification and optimization */ - FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) ); + FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , ""); return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictContentType, dtlm, cdict, @@ -3158,7 +3171,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) /* special case : empty frame */ if (cctx->stage == ZSTDcs_init) { fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0); - FORWARD_IF_ERROR(fhSize); + FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); dstCapacity -= fhSize; op += fhSize; cctx->stage = ZSTDcs_ongoing; @@ -3167,7 +3180,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) if (cctx->stage != ZSTDcs_ending) { /* write one last empty block, make it the "last" block */ U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; - RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue"); MEM_writeLE32(op, cBlockHeader24); op += ZSTD_blockHeaderSize; dstCapacity -= ZSTD_blockHeaderSize; @@ -3175,7 +3188,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) if (cctx->appliedParams.fParams.checksumFlag) { U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); - RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum); MEM_writeLE32(op, checksum); op += 4; @@ -3193,9 +3206,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 1 /* last chunk */); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed"); endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); - FORWARD_IF_ERROR(endResult); + FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed"); assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); @@ -3234,7 +3247,7 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, ZSTD_parameters params) { DEBUGLOG(4, "ZSTD_compress_advanced"); - FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams)); + FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); return ZSTD_compress_internal(cctx, dst, dstCapacity, src, srcSize, @@ -3253,7 +3266,7 @@ size_t ZSTD_compress_advanced_internal( DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize); FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, - params, srcSize, ZSTDb_not_buffered) ); + params, srcSize, ZSTDb_not_buffered) , ""); return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); } @@ -3337,7 +3350,7 @@ static size_t ZSTD_initCDict_internal( cdict->dictContent = dictBuffer; } else { void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*))); - RETURN_ERROR_IF(!internalBuffer, memory_allocation); + RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!"); cdict->dictContent = internalBuffer; memcpy(internalBuffer, dictBuffer, dictSize); } @@ -3354,7 +3367,7 @@ static size_t ZSTD_initCDict_internal( &cParams, ZSTDcrp_makeClean, ZSTDirp_reset, - ZSTD_resetTarget_CDict)); + ZSTD_resetTarget_CDict), ""); /* (Maybe) load the dictionary * Skips loading the dictionary if it is < 8 bytes. */ @@ -3367,7 +3380,7 @@ static size_t ZSTD_initCDict_internal( &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, ¶ms, cdict->dictContent, cdict->dictContentSize, dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace); - FORWARD_IF_ERROR(dictID); + FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); assert(dictID <= (size_t)(U32)-1); cdict->dictID = (U32)dictID; } @@ -3515,7 +3528,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced( ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) { DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced"); - RETURN_ERROR_IF(cdict==NULL, dictionary_wrong); + RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); { ZSTD_CCtx_params params = cctx->requestedParams; params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER @@ -3559,7 +3572,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, const void* src, size_t srcSize, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) { - FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */ + FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */ return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); } @@ -3631,7 +3644,7 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx, dict, dictSize, dictContentType, ZSTD_dtlm_fast, cdict, ¶ms, pledgedSrcSize, - ZSTDb_buffered) ); + ZSTDb_buffered) , ""); cctx->inToCompress = 0; cctx->inBuffPos = 0; @@ -3653,8 +3666,8 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss) */ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); return 0; } @@ -3668,16 +3681,16 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) { DEBUGLOG(4, "ZSTD_initCStream_internal"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); zcs->requestedParams = *params; assert(!((dict) && (cdict))); /* either dict or cdict, not both */ if (dict) { - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); } else { /* Dictionary is cleared if !cdict */ - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) ); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); } return 0; } @@ -3690,10 +3703,10 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize) { DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); zcs->requestedParams.fParams = fParams; - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) ); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); return 0; } @@ -3701,8 +3714,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) { DEBUGLOG(4, "ZSTD_initCStream_usingCDict"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); return 0; } @@ -3721,20 +3734,20 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, */ U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; DEBUGLOG(4, "ZSTD_initCStream_advanced"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, ¶ms); - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; } size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) { DEBUGLOG(4, "ZSTD_initCStream_usingDict"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) ); - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); return 0; } @@ -3746,19 +3759,19 @@ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigne */ U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; DEBUGLOG(4, "ZSTD_initCStream_srcSize"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); return 0; } size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) { DEBUGLOG(4, "ZSTD_initCStream"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) ); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) ); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); return 0; } @@ -3811,7 +3824,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, size_t const cSize = ZSTD_compressEnd(zcs, op, oend-op, ip, iend-ip); DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed"); ip = iend; op += cSize; zcs->frameEnded = 1; @@ -3853,7 +3866,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, zcs->inBuff + zcs->inToCompress, iSize) : ZSTD_compressContinue(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); zcs->frameEnded = lastBlock; /* prepare next block */ zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; @@ -3930,7 +3943,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx) size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { - FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) ); + FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , ""); return ZSTD_nextInputSizeHint_MTorST(zcs); } @@ -3942,15 +3955,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, { DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); /* check conditions */ - RETURN_ERROR_IF(output->pos > output->size, GENERIC); - RETURN_ERROR_IF(input->pos > input->size, GENERIC); + RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer"); + RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer"); assert(cctx!=NULL); /* transparent initialization stage */ if (cctx->streamStage == zcss_init) { ZSTD_CCtx_params params = cctx->requestedParams; ZSTD_prefixDict const prefixDict = cctx->prefixDict; - FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */ + FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); @@ -3969,14 +3982,14 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", params.nbWorkers); cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem); - RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation); + RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); } /* mt compression */ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( cctx->mtctx, prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) ); + cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); cctx->streamStage = zcss_load; cctx->appliedParams.nbWorkers = params.nbWorkers; } else @@ -3984,7 +3997,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx, prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, cctx->cdict, - params, cctx->pledgedSrcSizePlusOne-1) ); + params, cctx->pledgedSrcSizePlusOne-1) , ""); assert(cctx->streamStage == zcss_load); assert(cctx->appliedParams.nbWorkers == 0); } } @@ -4006,7 +4019,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); } - FORWARD_IF_ERROR(flushMin); + FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed"); } while (forceMaxProgress && flushMin != 0 && output->pos < output->size); DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); /* Either we don't require maximum forward progress, we've finished the @@ -4016,7 +4029,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, return flushMin; } #endif - FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) ); + FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , ""); DEBUGLOG(5, "completed ZSTD_compressStream2"); return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ } @@ -4047,10 +4060,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, dst, dstCapacity, &oPos, src, srcSize, &iPos, ZSTD_e_end); - FORWARD_IF_ERROR(result); + FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed"); if (result != 0) { /* compression not completed, due to lack of output space */ assert(oPos == dstCapacity); - RETURN_ERROR(dstSize_tooSmall); + RETURN_ERROR(dstSize_tooSmall, ""); } assert(iPos == srcSize); /* all input is expected consumed */ return oPos; @@ -4072,7 +4085,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) { ZSTD_inBuffer input = { NULL, 0, 0 }; size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end); - FORWARD_IF_ERROR( remainingToFlush ); + FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed"); if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ /* single thread mode : attempt to calculate remaining to flush more precisely */ { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index db7b89cebbd..3ef85f4637b 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -370,7 +370,7 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi { U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3); RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity, - dstSize_tooSmall); + dstSize_tooSmall, "dst buf too small for uncompressed block"); MEM_writeLE24(dst, cBlockHeader24); memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); return ZSTD_blockHeaderSize + srcSize; diff --git a/lib/compress/zstd_compress_literals.c b/lib/compress/zstd_compress_literals.c index b7680004606..17e7168d893 100644 --- a/lib/compress/zstd_compress_literals.c +++ b/lib/compress/zstd_compress_literals.c @@ -18,7 +18,7 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, BYTE* const ostart = (BYTE* const)dst; U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); - RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall); + RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, ""); switch(flSize) { diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index 07a03c8a3ae..23a5f3532c9 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -60,7 +60,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max, BYTE wksp[FSE_NCOUNTBOUND]; S16 norm[MaxSeq + 1]; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max)); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), ""); return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog); } @@ -234,15 +234,15 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, switch (type) { case set_rle: - FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max)); - RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall); + FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max), ""); + RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall, "not enough space"); *op = codeTable[0]; return 1; case set_repeat: memcpy(nextCTable, prevCTable, prevCTableSize); return 0; case set_basic: - FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize)); /* note : could be pre-calculated */ + FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */ return 0; case set_compressed: { S16 norm[MaxSeq + 1]; @@ -253,14 +253,14 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, nbSeq_1--; } assert(nbSeq_1 > 1); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max)); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), ""); { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ - FORWARD_IF_ERROR(NCountSize); - FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize)); + FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed"); + FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), ""); return NCountSize; } } - default: assert(0); RETURN_ERROR(GENERIC); + default: assert(0); RETURN_ERROR(GENERIC, "impossible to reach"); } } diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index fd475dcc243..4e77292e183 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -98,7 +98,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz /* Scan input and build symbol stats */ { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize); - FORWARD_IF_ERROR(largest); + FORWARD_IF_ERROR(largest, "HIST_count_wksp failed"); if (largest == srcSize) { DEBUGLOG(5, "set_rle"); hufMetadata->hType = set_rle; @@ -122,7 +122,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue, huffLog, nodeWksp, nodeWkspSize); - FORWARD_IF_ERROR(maxBits); + FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp"); huffLog = (U32)maxBits; { /* Build and write the CTable */ size_t const newCSize = HUF_estimateCompressedSize( @@ -209,7 +209,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL, prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable), cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); if (LLtype == set_compressed) fseMetadata->lastCountSize = countSize; op += countSize; @@ -233,7 +233,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable), cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); if (Offtype == set_compressed) fseMetadata->lastCountSize = countSize; op += countSize; @@ -255,7 +255,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML, prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable), cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize); + FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); if (MLtype == set_compressed) fseMetadata->lastCountSize = countSize; op += countSize; @@ -285,14 +285,14 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, &entropyMetadata->hufMetadata, ZSTD_disableLiteralsCompression(cctxParams), workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize); + FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed"); entropyMetadata->fseMetadata.fseTablesSize = ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr, &prevEntropy->fse, &nextEntropy->fse, cctxParams, &entropyMetadata->fseMetadata, workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize); + FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed"); return 0; } @@ -451,7 +451,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables *entropyWritten = 0; /* Sequences Header */ RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, - dstSize_tooSmall); + dstSize_tooSmall, ""); if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq; else if (nbSeq < LONGNBSEQ) @@ -487,7 +487,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables fseTables->litlengthCTable, llCode, sequences, nbSeq, longOffsets, bmi2); - FORWARD_IF_ERROR(bitstreamSize); + FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); op += bitstreamSize; /* zstd versions <= 1.3.4 mistakenly report corruption when * FSE_readNCount() receives a buffer < 4 bytes. @@ -552,7 +552,7 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable, &entropyMetadata->hufMetadata, literals, litSize, op, oend-op, bmi2, writeLitEntropy, litEntropyWritten); - FORWARD_IF_ERROR(cLitSize); + FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed"); if (cLitSize == 0) return 0; op += cLitSize; } @@ -563,7 +563,7 @@ static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, cctxParams, op, oend-op, bmi2, writeSeqEntropy, seqEntropyWritten); - FORWARD_IF_ERROR(cSeqSize); + FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed"); if (cSeqSize == 0) return 0; op += cSeqSize; } @@ -764,8 +764,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, bmi2, writeLitEntropy, writeSeqEntropy, &litEntropyWritten, &seqEntropyWritten, lastBlock && lastSequence); - FORWARD_IF_ERROR(cSize); - DEBUGLOG(5, "cSize = %zu | decompressedSize = %zu", cSize, decompressedSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed"); if (cSize > 0 && cSize < decompressedSize) { DEBUGLOG(5, "Committed the sub-block"); assert(ip + decompressedSize <= iend); @@ -831,7 +830,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, &entropyMetadata, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */)); + zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); return ZSTD_compressSubBlock_multi(&zc->seqStore, zc->blockState.prevCBlock, diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 5886893d711..91f812fa310 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -458,7 +458,7 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) { void* workspace = ZSTD_malloc(size, customMem); DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size); - RETURN_ERROR_IF(workspace == NULL, memory_allocation); + RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!"); ZSTD_cwksp_init(ws, workspace, size); return 0; } diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 12ebcd2b5bc..56186f506dc 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -1063,7 +1063,7 @@ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params) static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) { if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation); - FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) ); + FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , ""); mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers); if (mtctx->bufPool == NULL) return ERROR(memory_allocation); mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers); @@ -1279,7 +1279,7 @@ static size_t ZSTDMT_compress_advanced_internal( if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0)) return ERROR(memory_allocation); - FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */ + FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */ { unsigned u; for (u=0; uparams.nbWorkers) - FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) ); + FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) , ""); if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; @@ -2071,7 +2071,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */ size_t const jobSize = mtctx->inBuff.filled; assert(mtctx->inBuff.filled <= mtctx->targetSectionSize); - FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) ); + FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , ""); } /* check for potential compressed data ready to be flushed */ @@ -2085,7 +2085,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input) { - FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) ); + FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , ""); /* recommended next input size : fill current input buffer */ return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */ @@ -2102,7 +2102,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */ DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)", (U32)srcSize, (U32)endFrame); - FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) ); + FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , ""); } /* check if there is any data available to flush */ diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index e931597d80b..70477ca7d7b 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -107,7 +107,7 @@ ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict, /* load entropy tables */ RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy( &ddict->entropy, ddict->dictContent, ddict->dictSize)), - dictionary_corrupted); + dictionary_corrupted, ""); ddict->entropyPresent = 1; return 0; } @@ -133,7 +133,7 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ /* parse dictionary content */ - FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) ); + FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , ""); return 0; } diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 8353099b3fe..91adb8a6efe 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -210,7 +210,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size) static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format) { size_t const minInputSize = ZSTD_startingInputLength(format); - RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong); + RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, ""); { BYTE const fhd = ((const BYTE*)src)[minInputSize-1]; U32 const dictID= fhd & 3; @@ -258,7 +258,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s zfhPtr->frameType = ZSTD_skippableFrame; return 0; } - RETURN_ERROR(prefix_unknown); + RETURN_ERROR(prefix_unknown, ""); } /* ensure there is enough `srcSize` to fully read/decode frame header */ @@ -282,7 +282,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s if (!singleSegment) { BYTE const wlByte = ip[pos++]; U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; - RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge); + RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, ""); windowSize = (1ULL << windowLog); windowSize += (windowSize >> 3) * (wlByte&7); } @@ -354,14 +354,14 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize) size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE; U32 sizeU32; - RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong); + RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, ""); sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE); RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32, - frameParameter_unsupported); + frameParameter_unsupported, ""); { size_t const skippableSize = skippableHeaderSize + sizeU32; - RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong); + RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, ""); return skippableSize; } } @@ -441,7 +441,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he * harder. */ RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID), - dictionary_wrong); + dictionary_wrong, ""); #endif if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); return 0; @@ -578,9 +578,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, DEBUGLOG(5, "ZSTD_copyRawBlock"); if (dst == NULL) { if (srcSize == 0) return 0; - RETURN_ERROR(dstBuffer_null); + RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall); + RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); memcpy(dst, src, srcSize); return srcSize; } @@ -591,9 +591,9 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, { if (dst == NULL) { if (regenSize == 0) return 0; - RETURN_ERROR(dstBuffer_null); + RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall); + RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); memset(dst, b, regenSize); return regenSize; } @@ -618,15 +618,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* check */ RETURN_ERROR_IF( remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize, - srcSize_wrong); + srcSize_wrong, ""); /* Frame Header */ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal( ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format); if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize, - srcSize_wrong); - FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) ); + srcSize_wrong, ""); + FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , ""); ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize; } @@ -639,7 +639,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, ip += ZSTD_blockHeaderSize; remainingSrcSize -= ZSTD_blockHeaderSize; - RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong); + RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, ""); switch(blockProperties.blockType) { @@ -654,7 +654,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, break; case bt_reserved : default: - RETURN_ERROR(corruption_detected); + RETURN_ERROR(corruption_detected, "invalid block type"); } if (ZSTD_isError(decodedSize)) return decodedSize; @@ -670,14 +670,14 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) { RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize, - corruption_detected); + corruption_detected, ""); } if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); U32 checkRead; - RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong); + RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, ""); checkRead = MEM_readLE32(ip); - RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong); + RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); ip += 4; remainingSrcSize -= 4; } @@ -734,7 +734,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, (unsigned)magicNumber, ZSTD_MAGICNUMBER); if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { size_t const skippableSize = readSkippableFrameSize(src, srcSize); - FORWARD_IF_ERROR(skippableSize); + FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed"); assert(skippableSize <= srcSize); src = (const BYTE *)src + skippableSize; @@ -744,11 +744,11 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, if (ddict) { /* we were called from ZSTD_decompress_usingDDict */ - FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict)); + FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), ""); } else { /* this will initialize correctly with no dict if dict == NULL, so * use this in all cases but ddict */ - FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); + FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), ""); } ZSTD_checkContinuity(dctx, dst); @@ -818,7 +818,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1) size_t regenSize; ZSTD_DCtx* const dctx = ZSTD_createDCtx(); - RETURN_ERROR_IF(dctx==NULL, memory_allocation); + RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!"); regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); ZSTD_freeDCtx(dctx); return regenSize; @@ -911,7 +911,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_decodeFrameHeader: assert(src != NULL); memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); - FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize)); + FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), ""); dctx->expected = ZSTD_blockHeaderSize; dctx->stage = ZSTDds_decodeBlockHeader; return 0; @@ -958,7 +958,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case bt_raw : assert(srcSize <= dctx->expected); rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); - FORWARD_IF_ERROR(rSize); + FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed"); assert(rSize == srcSize); dctx->expected -= rSize; break; @@ -968,9 +968,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c break; case bt_reserved : /* should never happen */ default: - RETURN_ERROR(corruption_detected); + RETURN_ERROR(corruption_detected, "invalid block type"); } - FORWARD_IF_ERROR(rSize); + FORWARD_IF_ERROR(rSize, ""); RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum"); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); dctx->decodedSize += rSize; @@ -987,7 +987,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c RETURN_ERROR_IF( dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && dctx->decodedSize != dctx->fParams.frameContentSize, - corruption_detected); + corruption_detected, ""); if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ dctx->expected = 4; dctx->stage = ZSTDds_checkChecksum; @@ -1007,7 +1007,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); U32 const check32 = MEM_readLE32(src); DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); - RETURN_ERROR_IF(check32 != h32, checksum_wrong); + RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); dctx->expected = 0; dctx->stage = ZSTDds_getFrameHeaderSize; return 0; @@ -1028,7 +1028,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c default: assert(0); /* impossible */ - RETURN_ERROR(GENERIC); /* some compiler require default to do something */ + RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */ } } @@ -1052,7 +1052,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, const BYTE* dictPtr = (const BYTE*)dict; const BYTE* const dictEnd = dictPtr + dictSize; - RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted); + RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small"); assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */ dictPtr += 8; /* skip header = magic + dictID */ @@ -1071,16 +1071,16 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, dictPtr, dictEnd - dictPtr, workspace, workspaceSize); #endif - RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted); + RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, ""); dictPtr += hSize; } { short offcodeNCount[MaxOff+1]; unsigned offcodeMaxValue = MaxOff, offcodeLog; size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted); - RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, ""); + RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->OFTable, offcodeNCount, offcodeMaxValue, OF_base, OF_bits, @@ -1091,9 +1091,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted); - RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, ""); + RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->MLTable, matchlengthNCount, matchlengthMaxValue, ML_base, ML_bits, @@ -1104,9 +1104,9 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted); - RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted); - RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted); + RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, ""); + RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->LLTable, litlengthNCount, litlengthMaxValue, LL_base, LL_bits, @@ -1114,13 +1114,13 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, dictPtr += litlengthHeaderSize; } - RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted); + RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, ""); { int i; size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12)); for (i=0; i<3; i++) { U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4; RETURN_ERROR_IF(rep==0 || rep > dictContentSize, - dictionary_corrupted); + dictionary_corrupted, ""); entropy->rep[i] = rep; } } @@ -1138,7 +1138,7 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict /* load entropy tables */ { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize); - RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted); + RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, ""); dict = (const char*)dict + eSize; dictSize -= eSize; } @@ -1173,11 +1173,11 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) { - FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) ); + FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , ""); if (dict && dictSize) RETURN_ERROR_IF( ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)), - dictionary_corrupted); + dictionary_corrupted, ""); return 0; } @@ -1196,7 +1196,7 @@ size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) DEBUGLOG(4, "DDict is %s", dctx->ddictIsCold ? "~cold~" : "hot!"); } - FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) ); + FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , ""); if (ddict) { /* NULL ddict is equivalent to no dictionary */ ZSTD_copyDDictParameters(dctx, ddict); } @@ -1287,11 +1287,11 @@ size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType) { - RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong); + RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); if (dict && dictSize != 0) { dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem); - RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation); + RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!"); dctx->ddict = dctx->ddictLocal; dctx->dictUses = ZSTD_use_indefinitely; } @@ -1310,7 +1310,7 @@ size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSi size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) { - FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType)); + FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), ""); dctx->dictUses = ZSTD_use_once; return 0; } @@ -1327,8 +1327,8 @@ size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSiz size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize) { DEBUGLOG(4, "ZSTD_initDStream_usingDict"); - FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) ); + FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , ""); return ZSTD_startingInputLength(zds->format); } @@ -1344,8 +1344,8 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds) * this function cannot fail */ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) { - FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) ); - FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) ); + FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , ""); return ZSTD_startingInputLength(dctx->format); } @@ -1354,14 +1354,14 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) * this function cannot fail */ size_t ZSTD_resetDStream(ZSTD_DStream* dctx) { - FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only)); + FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), ""); return ZSTD_startingInputLength(dctx->format); } size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) { - RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong); + RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); if (ddict) { dctx->ddict = ddict; @@ -1378,9 +1378,9 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize) ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax); size_t const min = (size_t)1 << bounds.lowerBound; size_t const max = (size_t)1 << bounds.upperBound; - RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong); - RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound); - RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound); + RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); + RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, ""); + RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, ""); dctx->maxWindowSize = maxWindowSize; return 0; } @@ -1426,12 +1426,12 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value) } #define CHECK_DBOUNDS(p,v) { \ - RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound); \ + RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \ } size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) { - RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong); + RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); switch(dParam) { case ZSTD_d_windowLogMax: if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT; @@ -1448,7 +1448,7 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value return 0; default:; } - RETURN_ERROR(parameter_unsupported); + RETURN_ERROR(parameter_unsupported, ""); } size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) @@ -1460,7 +1460,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) } if ( (reset == ZSTD_reset_parameters) || (reset == ZSTD_reset_session_and_parameters) ) { - RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong); + RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); dctx->format = ZSTD_f_zstd1; dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; @@ -1481,7 +1481,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long unsigned long long const neededSize = MIN(frameContentSize, neededRBSize); size_t const minRBSize = (size_t) neededSize; RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize, - frameParameter_windowTooLarge); + frameParameter_windowTooLarge, ""); return minRBSize; } @@ -1499,9 +1499,9 @@ size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) ZSTD_frameHeader zfh; size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize); if (ZSTD_isError(err)) return err; - RETURN_ERROR_IF(err>0, srcSize_wrong); + RETURN_ERROR_IF(err>0, srcSize_wrong, ""); RETURN_ERROR_IF(zfh.windowSize > windowSizeMax, - frameParameter_windowTooLarge); + frameParameter_windowTooLarge, ""); return ZSTD_estimateDStreamSize((size_t)zfh.windowSize); } @@ -1557,7 +1557,7 @@ static size_t ZSTD_decompressContinueStream( size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart; size_t const decodedSize = ZSTD_decompressContinue(zds, zds->outBuff + zds->outStart, dstSize, src, srcSize); - FORWARD_IF_ERROR(decodedSize); + FORWARD_IF_ERROR(decodedSize, ""); if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; } else { @@ -1568,7 +1568,7 @@ static size_t ZSTD_decompressContinueStream( /* Write directly into the output buffer */ size_t const dstSize = isSkipFrame ? 0 : oend - *op; size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); - FORWARD_IF_ERROR(decodedSize); + FORWARD_IF_ERROR(decodedSize, ""); *op += decodedSize; /* Flushing is not needed. */ zds->streamStage = zdss_read; @@ -1602,7 +1602,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB "forbidden. out: pos: %u vs size: %u", (U32)output->pos, (U32)output->size); DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos)); - FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output)); + FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), ""); while (someMoreWork) { switch(zds->streamStage) @@ -1641,7 +1641,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB "legacy support is incompatible with static dctx"); FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion, - dict, dictSize)); + dict, dictSize), ""); zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input); if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */ @@ -1695,13 +1695,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* Consume header (see ZSTDds_decodeFrameHeader) */ DEBUGLOG(4, "Consume header"); - FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds))); + FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), ""); if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE); zds->stage = ZSTDds_skipFrame; } else { - FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize)); + FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), ""); zds->expected = ZSTD_blockHeaderSize; zds->stage = ZSTDds_decodeBlockHeader; } @@ -1712,7 +1712,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB (U32)(zds->maxWindowSize >> 10) ); zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize, - frameParameter_windowTooLarge); + frameParameter_windowTooLarge, ""); /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); @@ -1736,13 +1736,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ RETURN_ERROR_IF( bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), - memory_allocation); + memory_allocation, ""); } else { ZSTD_free(zds->inBuff, zds->customMem); zds->inBuffSize = 0; zds->outBuffSize = 0; zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); - RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation); + RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, ""); } zds->inBuffSize = neededInBuffSize; zds->outBuff = zds->inBuff + zds->inBuffSize; @@ -1761,7 +1761,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB break; } if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */ - FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize)); + FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), ""); ip += neededInSize; /* Function modifies the stage so we must break */ break; @@ -1791,7 +1791,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* decode loaded input */ zds->inPos = 0; /* input is consumed */ - FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize)); + FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), ""); /* Function modifies the stage so we must break */ break; } @@ -1817,7 +1817,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB default: assert(0); /* impossible */ - RETURN_ERROR(GENERIC); /* some compiler require default to do something */ + RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */ } } /* result */ @@ -1830,8 +1830,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if ((ip==istart) && (op==ostart)) { /* no forward progress */ zds->noForwardProgress ++; if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) { - RETURN_ERROR_IF(op==oend, dstSize_tooSmall); - RETURN_ERROR_IF(ip==iend, srcSize_wrong); + RETURN_ERROR_IF(op==oend, dstSize_tooSmall, ""); + RETURN_ERROR_IF(ip==iend, srcSize_wrong, ""); assert(0); } } else { diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 521daa3d14c..5a1226ebae7 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -56,7 +56,7 @@ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr) { - RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong); + RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, ""); { U32 const cBlockHeader = MEM_readLE24(src); U32 const cSize = cBlockHeader >> 3; @@ -64,7 +64,7 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); bpPtr->origSize = cSize; /* only useful for RLE */ if (bpPtr->blockType == bt_rle) return 1; - RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected); + RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, ""); return cSize; } } @@ -80,7 +80,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ { DEBUGLOG(5, "ZSTD_decodeLiteralsBlock"); - RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected); + RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); { const BYTE* const istart = (const BYTE*) src; symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); @@ -89,7 +89,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, { case set_repeat: DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block"); - RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted); + RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, ""); /* fall-through */ case set_compressed: @@ -121,8 +121,8 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, litCSize = (lhc >> 22) + ((size_t)istart[4] << 10); break; } - RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected); - RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected); + RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); + RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, ""); /* prefetch huffman table if cold */ if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) { @@ -160,7 +160,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, } } - RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected); + RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, ""); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; @@ -190,7 +190,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, } if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ - RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected); + RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, ""); memcpy(dctx->litBuffer, istart+lhSize, litSize); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; @@ -222,7 +222,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4"); break; } - RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected); + RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; @@ -440,8 +440,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb switch(type) { case set_rle : - RETURN_ERROR_IF(!srcSize, srcSize_wrong); - RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected); + RETURN_ERROR_IF(!srcSize, srcSize_wrong, ""); + RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, ""); { U32 const symbol = *(const BYTE*)src; U32 const baseline = baseValue[symbol]; U32 const nbBits = nbAdditionalBits[symbol]; @@ -453,7 +453,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb *DTablePtr = defaultTable; return 0; case set_repeat: - RETURN_ERROR_IF(!flagRepeatTable, corruption_detected); + RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, ""); /* prefetch FSE table if used */ if (ddictIsCold && (nbSeq > 24 /* heuristic */)) { const void* const pStart = *DTablePtr; @@ -465,8 +465,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb { unsigned tableLog; S16 norm[MaxSeq+1]; size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); - RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected); - RETURN_ERROR_IF(tableLog > maxLog, corruption_detected); + RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, ""); + RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, ""); ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); *DTablePtr = DTableSpace; return headerSize; @@ -487,28 +487,28 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, DEBUGLOG(5, "ZSTD_decodeSeqHeaders"); /* check */ - RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong); + RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, ""); /* SeqHead */ nbSeq = *ip++; if (!nbSeq) { *nbSeqPtr=0; - RETURN_ERROR_IF(srcSize != 1, srcSize_wrong); + RETURN_ERROR_IF(srcSize != 1, srcSize_wrong, ""); return 1; } if (nbSeq > 0x7F) { if (nbSeq == 0xFF) { - RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong); + RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, ""); nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; } else { - RETURN_ERROR_IF(ip >= iend, srcSize_wrong); + RETURN_ERROR_IF(ip >= iend, srcSize_wrong, ""); nbSeq = ((nbSeq-0x80)<<8) + *ip++; } } *nbSeqPtr = nbSeq; /* FSE table descriptors */ - RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong); /* minimum possible size: 1 byte for symbol encoding types */ + RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */ { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); @@ -521,7 +521,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, LL_base, LL_bits, LL_defaultDTable, dctx->fseEntropy, dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected); + RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += llhSize; } @@ -531,7 +531,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, OF_base, OF_bits, OF_defaultDTable, dctx->fseEntropy, dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected); + RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += ofhSize; } @@ -541,7 +541,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ML_base, ML_bits, ML_defaultDTable, dctx->fseEntropy, dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected); + RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += mlhSize; } } @@ -683,7 +683,7 @@ size_t ZSTD_execSequenceEnd(BYTE* op, /* copy Match */ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { /* offset beyond prefix */ - RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected); + RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); match = dictEnd - (prefixStart-match); if (match + sequence.matchLength <= dictEnd) { memmove(oLitEnd, match, sequence.matchLength); @@ -738,7 +738,7 @@ size_t ZSTD_execSequence(BYTE* op, /* Copy Match */ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { /* offset beyond prefix -> go into extDict */ - RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected); + RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); match = dictEnd + (match - prefixStart); if (match + sequence.matchLength <= dictEnd) { memmove(oLitEnd, match, sequence.matchLength); @@ -964,7 +964,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, { U32 i; for (i=0; ientropy.rep[i]; } RETURN_ERROR_IF( ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), - corruption_detected); + corruption_detected, ""); ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); @@ -1034,15 +1034,15 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, /* check if reached exact end */ DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); if (ZSTD_isError(error)) return error; - RETURN_ERROR_IF(nbSeq, corruption_detected); - RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected); + RETURN_ERROR_IF(nbSeq, corruption_detected, ""); + RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, ""); /* save reps for next block */ { U32 i; for (i=0; ientropy.rep[i] = (U32)(seqState.prevOffset[i]); } } /* last literal segment */ { size_t const lastLLSize = litEnd - litPtr; - RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall); + RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); memcpy(op, litPtr, lastLLSize); op += lastLLSize; } @@ -1096,7 +1096,7 @@ ZSTD_decompressSequencesLong_body( assert(iend >= ip); RETURN_ERROR_IF( ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), - corruption_detected); + corruption_detected, ""); ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); @@ -1106,7 +1106,7 @@ ZSTD_decompressSequencesLong_body( sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch); PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ } - RETURN_ERROR_IF(seqNb (size_t)(oend-op), dstSize_tooSmall); + RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); memcpy(op, litPtr, lastLLSize); op += lastLLSize; } @@ -1271,7 +1271,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)))); DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize); - RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong); + RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, ""); /* Decode literals section */ { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); From 2745f7a7d56a5cf73d41e274ad522045e9c6f920 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 12:26:29 -0400 Subject: [PATCH 308/402] Make Error Macro Invocation Without Info String Fail to Compile Even without `-pedantic`, these macros will now fail to compile unless you provide an info string argument. This will prevent us from regressing. --- lib/common/zstd_internal.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 950b789cf44..05225e32e24 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -62,8 +62,8 @@ extern "C" { */ #define RETURN_ERROR_IF(cond, err, ...) \ if (cond) { \ - RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ - RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s: ", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ + RAWLOG(3, __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ } @@ -75,8 +75,8 @@ extern "C" { */ #define RETURN_ERROR(err, ...) \ do { \ - RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ - RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s: ", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ + RAWLOG(3, __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ } while(0); @@ -90,8 +90,8 @@ extern "C" { do { \ size_t const err_code = (err); \ if (ERR_isError(err_code)) { \ - RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ - RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s: ", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ + RAWLOG(3, __VA_ARGS__); \ RAWLOG(3, "\n"); \ return err_code; \ } \ From 6696933b32444cbe63d0384f5407bd3cea265c6b Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 13:08:36 -0400 Subject: [PATCH 309/402] Make All Invocations Start With Literal Format String --- lib/compress/zstd_compress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a2ef61aee3a..22f5542eb08 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2761,7 +2761,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, { size_t const cSize = frame ? ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */); - FORWARD_IF_ERROR(cSize, frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed"); + FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed"); cctx->consumedSrcSize += srcSize; cctx->producedCSize += (cSize + fhSize); assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); @@ -3866,7 +3866,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, zcs->inBuff + zcs->inToCompress, iSize) : ZSTD_compressContinue(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); - FORWARD_IF_ERROR(cSize, lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); zcs->frameEnded = lastBlock; /* prepare next block */ zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; From 450542d3a7ab8922f96e8a334613d871b068c97b Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 13:09:14 -0400 Subject: [PATCH 310/402] Allow Empty Format Strings in Error Macro Invocations `-Wall` implies `-Wformat-zero-length`, which will cause compilation to fail under `-Werror` when an empty string is passed as the format string to a `printf`-family function. This commit moves us back to prefixing the provided format string, which successfully avoids that warning. However, this removes the failure mode where that `RAWLOG` invocation would fail to compile when no format string was provided at all (which was desirable to avoid having code that would successfully compile normally but fail under `-pedantic`, which *does* require that a non-zero number of args are provided). So this commit also introduces a function which does nothing at all, but will fail to compile if not provided with at least one argument, which is a string. This successfully links the compilability of pedantic and non-pedantic builds. --- lib/common/zstd_internal.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 05225e32e24..856ee14873a 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -53,6 +53,10 @@ extern "C" { #define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b)) +static INLINE_KEYWORD UNUSED_ATTR void _force_has_formatting_string(const char *format, ...) { + (void)format; +} + /** * Return the specified error if the condition evaluates to true. * @@ -62,8 +66,10 @@ extern "C" { */ #define RETURN_ERROR_IF(cond, err, ...) \ if (cond) { \ - RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s: ", __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ - RAWLOG(3, __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \ + __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ + _force_has_formatting_string(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ } @@ -75,8 +81,10 @@ extern "C" { */ #define RETURN_ERROR(err, ...) \ do { \ - RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s: ", __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ - RAWLOG(3, __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \ + __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ + _force_has_formatting_string(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ } while(0); @@ -90,8 +98,10 @@ extern "C" { do { \ size_t const err_code = (err); \ if (ERR_isError(err_code)) { \ - RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s: ", __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ - RAWLOG(3, __VA_ARGS__); \ + RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \ + __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ + _force_has_formatting_string(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return err_code; \ } \ From baa4e2e36c9c830424631a92d69b5c7308bcceb5 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 17:07:49 -0400 Subject: [PATCH 311/402] Don't Evaluate Arguments to Dummy Function --- lib/common/zstd_internal.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 856ee14873a..35fb3ee3f79 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -53,10 +53,30 @@ extern "C" { #define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b)) -static INLINE_KEYWORD UNUSED_ATTR void _force_has_formatting_string(const char *format, ...) { +/** + * Ignore: this is an internal helper. + * + * This is a helper function to help force C99-correctness during compilation. + * Under strict compilation modes, variadic macro arguments can't be empty. + * However, variadic function arguments can be. Using a function therefore lets + * us statically check that at least one (string) argument was passed, + * independent of the compilation flags. + */ +HINT_INLINE UNUSED_ATTR void _force_has_format_string(const char *format, ...) { (void)format; } +/** + * Ignore: this is an internal helper. + * + * We want to force this function invocation to be syntactically correct, but + * we don't want to force runtime evaluation of its arguments. + */ +#define _FORCE_HAS_FORMAT_STRING(...) \ + if (0) { \ + _force_has_format_string(__VA_ARGS__); \ + } + /** * Return the specified error if the condition evaluates to true. * @@ -68,7 +88,7 @@ static INLINE_KEYWORD UNUSED_ATTR void _force_has_formatting_string(const char * if (cond) { \ RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \ __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ - _force_has_formatting_string(__VA_ARGS__); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ @@ -83,7 +103,7 @@ static INLINE_KEYWORD UNUSED_ATTR void _force_has_formatting_string(const char * do { \ RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \ __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ - _force_has_formatting_string(__VA_ARGS__); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return ERROR(err); \ @@ -100,7 +120,7 @@ static INLINE_KEYWORD UNUSED_ATTR void _force_has_formatting_string(const char * if (ERR_isError(err_code)) { \ RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \ __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ - _force_has_formatting_string(__VA_ARGS__); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ RAWLOG(3, ": " __VA_ARGS__); \ RAWLOG(3, "\n"); \ return err_code; \ From 952427aebfbcb46299fa39ef1347d67929c2b3b4 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 17:20:40 -0400 Subject: [PATCH 312/402] Avoid inline Keyword in C90 Previously we would use it for all gcc-like compilations, even when a restrictive mode that disallowed it had been selected. --- lib/common/compiler.h | 2 +- lib/common/xxhash.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 2f18efb0a42..95e9483521d 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -17,7 +17,7 @@ /* force inlining */ #if !defined(ZSTD_NO_INLINE) -#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # define INLINE_KEYWORD inline #else # define INLINE_KEYWORD diff --git a/lib/common/xxhash.c b/lib/common/xxhash.c index 429a869e9a4..72314c59f36 100644 --- a/lib/common/xxhash.c +++ b/lib/common/xxhash.c @@ -95,7 +95,7 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp /* ************************************* * Compiler Specific Options ***************************************/ -#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # define INLINE_KEYWORD inline #else # define INLINE_KEYWORD From c7da66c9cf16929206913387b3a5b51d8daf056b Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 17:33:59 -0400 Subject: [PATCH 313/402] Purge C++-Style Comments (`// ...`), Make Compilation Succeed Under C90 --- lib/common/fse_decompress.c | 2 +- lib/compress/zstd_compress_internal.h | 2 +- lib/compress/zstd_compress_superblock.c | 12 ++++++------ lib/compress/zstd_opt.c | 2 +- lib/legacy/zstd_v01.c | 10 +++++----- lib/legacy/zstd_v02.c | 2 +- lib/legacy/zstd_v03.c | 2 +- lib/legacy/zstd_v04.c | 2 +- lib/legacy/zstd_v05.c | 16 ++++++++-------- lib/legacy/zstd_v06.c | 16 ++++++++-------- lib/legacy/zstd_v07.c | 12 ++++++------ 11 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lib/common/fse_decompress.c b/lib/common/fse_decompress.c index 9f948e1c046..bcc2223ccc6 100644 --- a/lib/common/fse_decompress.c +++ b/lib/common/fse_decompress.c @@ -262,7 +262,7 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size /* normal FSE decoding mode */ size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); if (FSE_isError(NCountLength)) return NCountLength; - //if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ + /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ if (tableLog > maxLog) return ERROR(tableLog_tooLarge); ip += NCountLength; cSrcSize -= NCountLength; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 3ef85f4637b..d95eb1bf90d 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -954,7 +954,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, window->dictLimit = (U32)distanceFromBase; window->dictBase = window->base; window->base = ip - distanceFromBase; - // ms->nextToUpdate = window->dictLimit; + /* ms->nextToUpdate = window->dictLimit; */ if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit; /* too small extDict */ contiguous = 0; } diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index 4e77292e183..e44a14b621a 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -28,7 +28,7 @@ * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */ typedef struct { symbolEncodingType_e hType; - BYTE hufDesBuffer[500]; // TODO give name to this value + BYTE hufDesBuffer[500]; /* TODO give name to this value */ size_t hufDesSize; } ZSTD_hufCTablesMetadata_t; @@ -41,9 +41,9 @@ typedef struct { symbolEncodingType_e llType; symbolEncodingType_e ofType; symbolEncodingType_e mlType; - BYTE fseTablesBuffer[500]; // TODO give name to this value + BYTE fseTablesBuffer[500]; /* TODO give name to this value */ size_t fseTablesSize; - size_t lastCountSize; // This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() + size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */ } ZSTD_fseCTablesMetadata_t; typedef struct { @@ -330,7 +330,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; size_t cLitSize = 0; - (void)bmi2; // TODO bmi2... + (void)bmi2; /* TODO bmi2... */ DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy); @@ -353,7 +353,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize); } - // TODO bmi2 + /* TODO bmi2 */ { const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable) : HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable); op += cSize; @@ -801,7 +801,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, if (ip < iend) { size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock); DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip)); - FORWARD_IF_ERROR(cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); assert(cSize != 0); op += cSize; /* We have to regenerate the repcodes because we've skipped some sequences */ diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 8d63019654e..890ae9243e1 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -781,7 +781,7 @@ listStats(const U32* table, int lastEltID) int enb; for (enb=0; enb < nbElts; enb++) { (void)table; - //RAWLOG(2, "%3i:%3i, ", enb, table[enb]); + /* RAWLOG(2, "%3i:%3i, ", enb, table[enb]); */ RAWLOG(2, "%4i,", table[enb]); } RAWLOG(2, " \n"); diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index f8eb21db8a3..4d5ecf7d324 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -257,7 +257,7 @@ static U64 FSE_read64(const void* memPtr) U64 val; memcpy(&val, memPtr, sizeof(val)); return val; } -#endif // FSE_FORCE_MEMORY_ACCESS +#endif /* FSE_FORCE_MEMORY_ACCESS */ static U16 FSE_readLE16(const void* memPtr) { @@ -1092,7 +1092,7 @@ static size_t HUF_decompress_usingDTable( /* -3% slower when non static */ const size_t length1 = FSE_readLE16(jumpTable); const size_t length2 = FSE_readLE16(jumpTable+1); const size_t length3 = FSE_readLE16(jumpTable+2); - const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; // check coherency !! + const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; /* check coherency !! */ const char* const start1 = (const char*)(cSrc) + 6; const char* const start2 = start1 + length1; const char* const start3 = start2 + length2; @@ -1150,11 +1150,11 @@ static size_t HUF_decompress_usingDTable( /* -3% slower when non static */ /* tail */ { - // bitTail = bitD1; // *much* slower : -20% !??! + /* bitTail = bitD1; */ /* *much* slower : -20% !??! */ FSE_DStream_t bitTail; bitTail.ptr = bitD1.ptr; bitTail.bitsConsumed = bitD1.bitsConsumed; - bitTail.bitContainer = bitD1.bitContainer; // required in case of FSE_DStream_endOfBuffer + bitTail.bitContainer = bitD1.bitContainer; /* required in case of FSE_DStream_endOfBuffer */ bitTail.start = start1; for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op> 3) & 7) << 16; // mmmmh.... + litSize += ((ip[-3] >> 3) & 7) << 16; /* mmmmh.... */ op = oend - litSize; (void)ctx; diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index dc4a3e8a863..7105aa49a6b 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -189,7 +189,7 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value) memcpy(memPtr, &value, sizeof(value)); } -#endif // MEM_FORCE_MEMORY_ACCESS +#endif /* MEM_FORCE_MEMORY_ACCESS */ MEM_STATIC U16 MEM_readLE16(const void* memPtr) diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index f0c26b8eb18..980cf02f1c9 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -191,7 +191,7 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value) } -#endif // MEM_FORCE_MEMORY_ACCESS +#endif /* MEM_FORCE_MEMORY_ACCESS */ MEM_STATIC U16 MEM_readLE16(const void* memPtr) diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index bf344543846..e5b51f7823e 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -161,7 +161,7 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value) memcpy(memPtr, &value, sizeof(value)); } -#endif // MEM_FORCE_MEMORY_ACCESS +#endif /* MEM_FORCE_MEMORY_ACCESS */ MEM_STATIC U16 MEM_readLE16(const void* memPtr) diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 07355ecb6cc..649144d0438 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -1804,7 +1804,7 @@ static size_t HUFv05_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, if (!srcSize) return ERROR(srcSize_wrong); iSize = ip[0]; - //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ if (iSize >= (242)) { /* RLE */ @@ -1879,7 +1879,7 @@ size_t HUFv05_readDTableX2 (U16* DTable, const void* src, size_t srcSize) HUFv05_DEltX2* const dt = (HUFv05_DEltX2*)dtPtr; HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ - //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv05_readStats(huffWeight, HUFv05_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); if (HUFv05_isError(iSize)) return iSize; @@ -2210,7 +2210,7 @@ size_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize) HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX4) == sizeof(unsigned)); /* if compilation fails here, assertion is false */ if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); - //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ + /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); if (HUFv05_isError(iSize)) return iSize; @@ -2539,9 +2539,9 @@ size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); - //return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */ - //return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */ - //return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); /* multi-streams quad-symbols decoding */ + /* return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */ + /* return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */ + /* return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams quad-symbols decoding */ } /* zstd - standard compression library @@ -3930,7 +3930,7 @@ size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDst *maxDstSizePtr = 0; return headerSize - zbc->hPos; } - // zbc->stage = ZBUFFv05ds_decodeHeader; break; /* useless : stage follows */ + /* zbc->stage = ZBUFFv05ds_decodeHeader; break; */ /* useless : stage follows */ } /* fall-through */ case ZBUFFv05ds_decodeHeader: @@ -4003,7 +4003,7 @@ size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDst if (!decodedSize) { zbc->stage = ZBUFFv05ds_read; break; } /* this was just a header */ zbc->outEnd = zbc->outStart + decodedSize; zbc->stage = ZBUFFv05ds_flush; - // break; /* ZBUFFv05ds_flush follows */ + /* break; */ /* ZBUFFv05ds_flush follows */ } } /* fall-through */ diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index b957e5b0ce2..288eebe8177 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -1862,7 +1862,7 @@ MEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankSta if (!srcSize) return ERROR(srcSize_wrong); iSize = ip[0]; - //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ if (iSize >= (242)) { /* RLE */ @@ -2014,7 +2014,7 @@ size_t HUFv06_readDTableX2 (U16* DTable, const void* src, size_t srcSize) HUFv06_DEltX2* const dt = (HUFv06_DEltX2*)dtPtr; HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ - //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv06_readStats(huffWeight, HUFv06_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); if (HUFv06_isError(iSize)) return iSize; @@ -2340,7 +2340,7 @@ size_t HUFv06_readDTableX4 (U32* DTable, const void* src, size_t srcSize) HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */ if (memLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); - //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ + /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv06_readStats(weightList, HUFv06_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); if (HUFv06_isError(iSize)) return iSize; @@ -2664,13 +2664,13 @@ size_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS { U32 algoNb = 0; if (Dtime[1] < Dtime[0]) algoNb = 1; - // if (Dtime[2] < Dtime[algoNb]) algoNb = 2; /* current speed of HUFv06_decompress4X6 is not good */ + /* if (Dtime[2] < Dtime[algoNb]) algoNb = 2; */ /* current speed of HUFv06_decompress4X6 is not good */ return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); } - //return HUFv06_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */ - //return HUFv06_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */ - //return HUFv06_decompress4X6(dst, dstSize, cSrc, cSrcSize); /* multi-streams quad-symbols decoding */ + /* return HUFv06_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */ + /* return HUFv06_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */ + /* return HUFv06_decompress4X6(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams quad-symbols decoding */ } /* Common functions of Zstd compression library @@ -4111,7 +4111,7 @@ size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* zbd, if (!decodedSize) { zbd->stage = ZBUFFds_read; break; } /* this was just a header */ zbd->outEnd = zbd->outStart + decodedSize; zbd->stage = ZBUFFds_flush; - // break; /* ZBUFFds_flush follows */ + /* break; */ /* ZBUFFds_flush follows */ } } /* fall-through */ diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index 1a93bb93d8f..36593d38b5b 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -1314,7 +1314,7 @@ size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, if (!srcSize) return ERROR(srcSize_wrong); iSize = ip[0]; - //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ if (iSize >= (242)) { /* RLE */ @@ -1784,7 +1784,7 @@ size_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSi HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr; HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable)); - //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ + /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); if (HUFv07_isError(iSize)) return iSize; @@ -2148,7 +2148,7 @@ size_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSi HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable)); /* if compilation fails here, assertion is false */ if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge); - //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ + /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); if (HUFv07_isError(iSize)) return iSize; @@ -2530,8 +2530,8 @@ size_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); } - //return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); /* multi-streams single-symbol decoding */ - //return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); /* multi-streams double-symbols decoding */ + /* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams single-symbol decoding */ + /* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */ /* multi-streams double-symbols decoding */ } size_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) @@ -3712,7 +3712,7 @@ static size_t ZSTDv07_decompressSequences( /* last literal segment */ { size_t const lastLLSize = litEnd - litPtr; - //if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */ + /* if (litPtr > litEnd) return ERROR(corruption_detected); */ /* too many literals already used */ if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); memcpy(op, litPtr, lastLLSize); op += lastLLSize; From 37648590601476fe518db9b1e2f32703f50aa3ae Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 30 Apr 2020 17:43:20 -0400 Subject: [PATCH 314/402] Switch Helper Declaration to Not Force Inline It was causing build issues in ANSI mode. --- lib/common/zstd_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 35fb3ee3f79..57a6137e154 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -62,7 +62,8 @@ extern "C" { * us statically check that at least one (string) argument was passed, * independent of the compilation flags. */ -HINT_INLINE UNUSED_ATTR void _force_has_format_string(const char *format, ...) { +static INLINE_KEYWORD UNUSED_ATTR +void _force_has_format_string(const char *format, ...) { (void)format; } From dacbcd2cc1741ba5aaf7eb8f3f4502b4d2144b26 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 12:24:51 -0400 Subject: [PATCH 315/402] Fix Up Some Pointer Handling in Tests --- tests/fuzzer.c | 29 +++++++++++++++++++++++++---- tests/zstreamtest.c | 6 +++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 700cb577160..52bc02c48a6 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -28,6 +28,7 @@ #undef NDEBUG #include #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressContinue, ZSTD_compressBlock */ +#include "debug.h" /* DEBUG_STATIC_ASSERT */ #include "fse.h" #include "zstd.h" /* ZSTD_VERSION_STRING */ #include "zstd_errors.h" /* ZSTD_getErrorCode */ @@ -456,10 +457,30 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : misc unaccounted for zstd symbols : ", testNb++); { - DISPLAYLEVEL(3, "%p ", ZSTD_getDictID_fromDDict); - DISPLAYLEVEL(3, "%p ", ZSTD_createDStream_advanced); - DISPLAYLEVEL(3, "%p ", ZSTD_copyDCtx); - DISPLAYLEVEL(3, "%p ", ZSTD_nextInputType); + /* %p takes a void*. In ISO C, it's illegal to cast a function pointer + * to a data pointer. (Although in POSIX you're required to be allowed + * to do it...) So we have to fall back to our trusty friend memcpy. */ + unsigned (* const funcptr_getDictID)(const ZSTD_DDict* ddict) = + ZSTD_getDictID_fromDDict; + ZSTD_DStream* (* const funcptr_createDStream)( + ZSTD_customMem customMem) = ZSTD_createDStream_advanced; + void (* const funcptr_copyDCtx)( + ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx) = ZSTD_copyDCtx; + ZSTD_nextInputType_e (* const funcptr_nextInputType)(ZSTD_DCtx* dctx) = + ZSTD_nextInputType; + const void *voidptr_getDictID; + const void *voidptr_createDStream; + const void *voidptr_copyDCtx; + const void *voidptr_nextInputType; + DEBUG_STATIC_ASSERT(sizeof(funcptr_getDictID) == sizeof(voidptr_getDictID)); + memcpy(&voidptr_getDictID , &funcptr_getDictID , sizeof(void*)); + memcpy(&voidptr_createDStream, &funcptr_createDStream, sizeof(void*)); + memcpy(&voidptr_copyDCtx , &funcptr_copyDCtx , sizeof(void*)); + memcpy(&voidptr_nextInputType, &funcptr_nextInputType, sizeof(void*)); + DISPLAYLEVEL(3, "%p ", voidptr_getDictID); + DISPLAYLEVEL(3, "%p ", voidptr_createDStream); + DISPLAYLEVEL(3, "%p ", voidptr_copyDCtx); + DISPLAYLEVEL(3, "%p ", voidptr_nextInputType); } DISPLAYLEVEL(3, ": OK \n"); diff --git a/tests/zstreamtest.c b/tests/zstreamtest.c index 3fc96eb11bf..79d5a8281bb 100644 --- a/tests/zstreamtest.c +++ b/tests/zstreamtest.c @@ -1452,12 +1452,12 @@ static int basicUnitTests(U32 seed, double compressibility) /* and includes a very long backref */ cursegmentlen = 128; - memcpy(inbuf + inbufpos, dictionary.start + 256, cursegmentlen); + memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 256, cursegmentlen); inbufpos += cursegmentlen; /* and includes a very long backref */ cursegmentlen = 128; - memcpy(inbuf + inbufpos, dictionary.start + 128, cursegmentlen); + memcpy(inbuf + inbufpos, (BYTE*)dictionary.start + 128, cursegmentlen); inbufpos += cursegmentlen; ret = ZSTD_compress_usingCDict(zc, outbuf, outbufsize, inbuf, inbufpos, cdict); @@ -1500,7 +1500,7 @@ static int basicUnitTests(U32 seed, double compressibility) } /* Write several very long offset matches into the dictionary */ for (offset = 1024; offset >= 0; offset -= 128) { - ZSTD_inBuffer in = {dictionary.start + offset, 128, 0}; + ZSTD_inBuffer in = {(BYTE*)dictionary.start + offset, 128, 0}; ZSTD_EndDirective flush = offset > 0 ? ZSTD_e_continue : ZSTD_e_end; CHECK_Z(ZSTD_compressStream2(zc, &out, &in, flush)); CHECK(in.pos != in.size, "input not fully consumed"); From 6528fa088e63c7ae6423e0d42eb5d0fb697a65dd Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 12:26:20 -0400 Subject: [PATCH 316/402] Do a `-pedantic` Build in CircleCI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca24f41a9e6..bcf2e1d5ea2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,7 +13,7 @@ jobs: name: Test command: | ./tests/test-license.py - cc -v; CFLAGS="-O0 -Werror" make all && make clean + cc -v; CFLAGS="-O0 -Werror -pedantic" make all && make clean make c99build ; make clean make c11build ; make clean make aarch64build ; make clean From 2cf72d56a68d1730dac0ee811a30d3909b535723 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 16:48:21 -0400 Subject: [PATCH 317/402] Try to Fix MSVC Error It's complaining about the `memcpy`s, saying: "warning C4090: 'function': different 'const' qualifiers" Let's try explicitly casting to the argument types... --- tests/fuzzer.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 52bc02c48a6..233468106a4 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -473,10 +473,22 @@ static int basicUnitTests(U32 const seed, double compressibility) const void *voidptr_copyDCtx; const void *voidptr_nextInputType; DEBUG_STATIC_ASSERT(sizeof(funcptr_getDictID) == sizeof(voidptr_getDictID)); - memcpy(&voidptr_getDictID , &funcptr_getDictID , sizeof(void*)); - memcpy(&voidptr_createDStream, &funcptr_createDStream, sizeof(void*)); - memcpy(&voidptr_copyDCtx , &funcptr_copyDCtx , sizeof(void*)); - memcpy(&voidptr_nextInputType, &funcptr_nextInputType, sizeof(void*)); + memcpy( + (void*)&voidptr_getDictID, + (const void*)&funcptr_getDictID, + sizeof(void*)); + memcpy( + (void*)&voidptr_createDStream, + (const void*)&funcptr_createDStream, + sizeof(void*)); + memcpy( + (void*)&voidptr_copyDCtx, + (const void*)&funcptr_copyDCtx, + sizeof(void*)); + memcpy( + (void*)&voidptr_nextInputType, + (const void*)&funcptr_nextInputType, + sizeof(void*)); DISPLAYLEVEL(3, "%p ", voidptr_getDictID); DISPLAYLEVEL(3, "%p ", voidptr_createDStream); DISPLAYLEVEL(3, "%p ", voidptr_copyDCtx); From fa5e01c467b994f35e9ca321dfb510766033bfd8 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 27 Jan 2020 17:14:08 -0500 Subject: [PATCH 318/402] Add Space-Optimized Helper Variable to Lib Makefile This diff reorganizes the `lib/Makefile` to extract various settings that a user would normally invoke together (supposing that they were aware of them) if they were trying to build the smallest `libzstd` possible. It collects these settings under a master setting `ZSTD_LIB_MIN_SIZE`. Also document this new option. --- lib/Makefile | 33 ++++++++++++++++++++++++++++++--- lib/README.md | 48 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index ac38867a931..025de8e54d7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -24,7 +24,6 @@ CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_ ifeq ($(OS),Windows_NT) # MinGW assumed CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting endif -CFLAGS ?= -O3 DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ -Wstrict-prototypes -Wundef -Wpointer-arith \ @@ -51,18 +50,46 @@ ifeq ($(findstring GCC,$(CCVER)),GCC) decompress/zstd_decompress_block.o : CFLAGS+=-fno-tree-vectorize endif -ZSTD_LEGACY_SUPPORT ?= 5 +# This is a helper variable that configures a bunch of other variables to new, +# space-optimized defaults. +ZSTD_LIB_MINIFY ?= 0 +ifneq ($(ZSTD_LIB_MINIFY), 0) + HAVE_CC_OZ ?= $(shell echo "" | $(CC) -Oz -x c -c - -o /dev/null 2> /dev/null && echo 1 || echo 0) + ZSTD_LEGACY_SUPPORT ?= 0 + ZSTD_LIB_DEPRECATED ?= 0 + HUF_FORCE_DECOMPRESS_X1 ?= 1 + ZSTD_FORCE_DECOMPRESS_SHORT ?= 1 + ZSTD_NO_INLINE ?= 1 + ZSTD_STRIP_ERROR_STRINGS ?= 1 + ifneq ($(HAVE_CC_OZ), 0) + # Some compilers (clang) support an even more space-optimized setting. + CFLAGS += -Oz + else + CFLAGS += -Os + endif + CFLAGS += -fno-stack-protector -fomit-frame-pointer -fno-ident \ + -DDYNAMIC_BMI2=0 -DNDEBUG +else + CFLAGS += -O3 +endif + +# Modules ZSTD_LIB_COMPRESSION ?= 1 ZSTD_LIB_DECOMPRESSION ?= 1 ZSTD_LIB_DICTBUILDER ?= 1 ZSTD_LIB_DEPRECATED ?= 1 + +# Legacy support +ZSTD_LEGACY_SUPPORT ?= 5 +ZSTD_LEGACY_MULTITHREADED_API ?= 0 + +# Build size optimizations HUF_FORCE_DECOMPRESS_X1 ?= 0 HUF_FORCE_DECOMPRESS_X2 ?= 0 ZSTD_FORCE_DECOMPRESS_SHORT ?= 0 ZSTD_FORCE_DECOMPRESS_LONG ?= 0 ZSTD_NO_INLINE ?= 0 ZSTD_STRIP_ERROR_STRINGS ?= 0 -ZSTD_LEGACY_MULTITHREADED_API ?= 0 ifeq ($(ZSTD_LIB_COMPRESSION), 0) ZSTD_LIB_DICTBUILDER = 0 diff --git a/lib/README.md b/lib/README.md index 0062c0d63e0..6ccffb13868 100644 --- a/lib/README.md +++ b/lib/README.md @@ -85,28 +85,48 @@ The file structure is designed to make this selection manually achievable for an - While invoking `make libzstd`, it's possible to define build macros `ZSTD_LIB_COMPRESSION, ZSTD_LIB_DECOMPRESSION`, `ZSTD_LIB_DICTBUILDER`, - and `ZSTD_LIB_DEPRECATED` as `0` to forgo compilation of the corresponding features. - This will also disable compilation of all dependencies - (eg. `ZSTD_LIB_COMPRESSION=0` will also disable dictBuilder). - -- There are some additional build macros that can be used to minify the decoder. - - Zstandard often has more than one implementation of a piece of functionality, - where each implementation optimizes for different scenarios. For example, the - Huffman decoder has complementary implementations that decode the stream one - symbol at a time or two symbols at a time. Zstd normally includes both (and - dispatches between them at runtime), but by defining `HUF_FORCE_DECOMPRESS_X1` - or `HUF_FORCE_DECOMPRESS_X2`, you can force the use of one or the other, avoiding + and `ZSTD_LIB_DEPRECATED` as `0` to forgo compilation of the + corresponding features. This will also disable compilation of all + dependencies (eg. `ZSTD_LIB_COMPRESSION=0` will also disable + dictBuilder). + +- There are a number of options that can help minimize the binary size of + `libzstd`. + + The first step is to select the components needed (using the above-described + `ZSTD_LIB_COMPRESSION` etc.). + + The next step is to set `ZSTD_LIB_MINIFY` to `1` when invoking `make`. This + disables various optional components and changes the compilation flags to + prioritize space-saving. + + Detailed options: Zstandard's code and build environment is set up by default + to optimize above all else for performance. In pursuit of this goal, Zstandard + makes significant trade-offs in code size. For example, Zstandard often has + more than one implementation of a particular component, with each + implementation optimized for different scenarios. For example, the Huffman + decoder has complementary implementations that decode the stream one symbol at + a time or two symbols at a time. Zstd normally includes both (and dispatches + between them at runtime), but by defining `HUF_FORCE_DECOMPRESS_X1` or + `HUF_FORCE_DECOMPRESS_X2`, you can force the use of one or the other, avoiding compilation of the other. Similarly, `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT` and `ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG` force the compilation and use of only one or the other of two decompression implementations. The smallest binary is achieved by using `HUF_FORCE_DECOMPRESS_X1` and - `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT`. + `ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT` (implied by `ZSTD_LIB_MINIFY`). For squeezing the last ounce of size out, you can also define `ZSTD_NO_INLINE`, which disables inlining, and `ZSTD_STRIP_ERROR_STRINGS`, which removes the error messages that are otherwise returned by - `ZSTD_getErrorName`. + `ZSTD_getErrorName` (implied by `ZSTD_LIB_MINIFY`). + + Finally, when integrating into your application, make sure you're doing link- + time optimation and unused symbol garbage collection (via some combination of, + e.g., `-flto`, `-ffat-lto-objects`, `-fuse-linker-plugin`, + `-ffunction-sections`, `-fdata-sections`, `-fmerge-all-constants`, + `-Wl,--gc-sections`, `-Wl,-z,norelro`, and an archiver that understands + the compiler's intermediate representation, e.g., `AR=gcc-ar`). Consult your + compiler's documentation. - While invoking `make libzstd`, the build macro `ZSTD_LEGACY_MULTITHREADED_API=1` will expose the deprecated `ZSTDMT` API exposed by `zstdmt_compress.h` in From 0b810351014c7b0e5e4ac1972d2453789f096700 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 4 May 2020 11:22:07 -0400 Subject: [PATCH 319/402] Test Flag in Travis CI --- .travis.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index aeaae729269..eae5bb63b1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -93,17 +93,13 @@ matrix: - name: Minimal Decompressor Macros # ~5mn script: - make clean - - CFLAGS=-Werror make -j all MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X1 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT" + - make -j all check ZSTD_LIB_MINIFY=1 MOREFLAGS="-Werror" - make clean - - make -j check MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X1 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT" + - make -j all check MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X1 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT" - make clean - - CFLAGS=-Werror make -j all MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X2 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG" + - make -j all check MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X2 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG" - make clean - - make -j check MOREFLAGS="-Werror -DHUF_FORCE_DECOMPRESS_X2 -DZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG" - - make clean - - CFLAGS=-Werror make -j all MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - - make clean - - make -j check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" + - make -j all check MOREFLAGS="-Werror -DZSTD_NO_INLINE -DZSTD_STRIP_ERROR_STRINGS" - name: cmake build and test check # ~6mn script: From 0301ef5d0463f53e88d589233b5f16c8d57e7295 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 4 May 2020 12:42:22 -0500 Subject: [PATCH 320/402] [bench] Extending largeNbDicts to compression (#2089) * adding cdict_collection_t * adding shuffleCDictionaries() * adding compressInstructions * adding compress() * integrating compression into bench() * copy paste error fix * static analyzer uninit value complaint fix * changing to control * removing assert * changing to control * moving memcpy to seperate function * fixing static analyzer complaint * another hacky solution attempt * Copying createbuffer logic --- contrib/largeNbDicts/largeNbDicts.c | 207 ++++++++++++++++++++++++---- 1 file changed, 184 insertions(+), 23 deletions(-) diff --git a/contrib/largeNbDicts/largeNbDicts.c b/contrib/largeNbDicts/largeNbDicts.c index 121cf2f9916..c84d48b2496 100644 --- a/contrib/largeNbDicts/largeNbDicts.c +++ b/contrib/largeNbDicts/largeNbDicts.c @@ -334,6 +334,42 @@ createBufferCollection_fromSliceCollectionSizes(slice_collection_t sc) return result; } +static buffer_collection_t +createBufferCollection_fromSliceCollection(slice_collection_t sc) +{ + size_t const bufferSize = sliceCollection_totalCapacity(sc); + + buffer_t buffer = createBuffer(bufferSize); + CONTROL(buffer.ptr != NULL); + + size_t const nbSlices = sc.nbSlices; + void** const slices = (void**)malloc(nbSlices * sizeof(*slices)); + CONTROL(slices != NULL); + + size_t* const capacities = (size_t*)malloc(nbSlices * sizeof(*capacities)); + CONTROL(capacities != NULL); + + char* const ptr = (char*)buffer.ptr; + size_t pos = 0; + for (size_t n=0; n < nbSlices; n++) { + capacities[n] = sc.capacities[n]; + slices[n] = ptr + pos; + pos += capacities[n]; + } + + for (size_t i = 0; i < nbSlices; i++) { + memcpy(slices[i], sc.slicePtrs[i], sc.capacities[i]); + capacities[i] = sc.capacities[i]; + } + + buffer_collection_t result; + result.buffer = buffer; + result.slices.nbSlices = nbSlices; + result.slices.capacities = capacities; + result.slices.slicePtrs = slices; + + return result; +} /* @return : kBuffNull if any error */ static buffer_collection_t @@ -397,6 +433,36 @@ typedef struct { size_t nbDDict; } ddict_collection_t; +typedef struct { + ZSTD_CDict** cdicts; + size_t nbCDict; +} cdict_collection_t; + +static const cdict_collection_t kNullCDictCollection = { NULL, 0 }; + +static void freeCDictCollection(cdict_collection_t cdictc) +{ + for (size_t dictNb=0; dictNb < cdictc.nbCDict; dictNb++) { + ZSTD_freeCDict(cdictc.cdicts[dictNb]); + } + free(cdictc.cdicts); +} + +/* returns .buffers=NULL if operation fails */ +static cdict_collection_t createCDictCollection(const void* dictBuffer, size_t dictSize, size_t nbCDict, int cLevel) +{ + ZSTD_CDict** const cdicts = malloc(nbCDict * sizeof(ZSTD_CDict*)); + if (cdicts==NULL) return kNullCDictCollection; + for (size_t dictNb=0; dictNb < nbCDict; dictNb++) { + cdicts[dictNb] = ZSTD_createCDict(dictBuffer, dictSize, cLevel); + CONTROL(cdicts[dictNb] != NULL); + } + cdict_collection_t cdictc; + cdictc.cdicts = cdicts; + cdictc.nbCDict = nbCDict; + return cdictc; +} + static const ddict_collection_t kNullDDictCollection = { NULL, 0 }; static void freeDDictCollection(ddict_collection_t ddictc) @@ -425,7 +491,26 @@ static ddict_collection_t createDDictCollection(const void* dictBuffer, size_t d /* mess with addresses, so that linear scanning dictionaries != linear address scanning */ -void shuffleDictionaries(ddict_collection_t dicts) +void shuffleCDictionaries(cdict_collection_t dicts) +{ + size_t const nbDicts = dicts.nbCDict; + for (size_t r=0; rcctx, + dst, srcSize, + src, srcSize, + ci->dictionaries.cdicts[ci->dictNb]); + + ci->dictNb = ci->dictNb + 1; + if (ci->dictNb >= ci->nbDicts) ci->dictNb = 0; + + return srcSize; +} + /* benched function */ size_t decompress(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* payload) { @@ -527,8 +652,9 @@ size_t decompress(const void* src, size_t srcSize, void* dst, size_t dstCapacity static int benchMem(slice_collection_t dstBlocks, slice_collection_t srcBlocks, - ddict_collection_t dictionaries, - unsigned nbRounds) + ddict_collection_t ddictionaries, + cdict_collection_t cdictionaries, + unsigned nbRounds, int benchCompression) { assert(dstBlocks.nbSlices == srcBlocks.nbSlices); @@ -539,10 +665,13 @@ static int benchMem(slice_collection_t dstBlocks, BMK_timedFnState_t* const benchState = BMK_createTimedFnState(total_time_ms, ms_per_round); - decompressInstructions di = createDecompressInstructions(dictionaries); + + decompressInstructions di = createDecompressInstructions(ddictionaries); + compressInstructions ci = createCompressInstructions(cdictionaries); + void* payload = benchCompression ? (void*)&ci : (void*)&di; BMK_benchParams_t const bp = { - .benchFn = decompress, - .benchPayload = &di, + .benchFn = benchCompression ? compress : decompress, + .benchPayload = payload, .initFn = NULL, .initPayload = NULL, .errorFn = ZSTD_isError, @@ -562,15 +691,20 @@ static int benchMem(slice_collection_t dstBlocks, double const dTime_ns = result.nanoSecPerRun; double const dTime_sec = (double)dTime_ns / 1000000000; size_t const srcSize = result.sumOfReturn; - double const dSpeed_MBps = (double)srcSize / dTime_sec / (1 MB); - if (dSpeed_MBps > bestSpeed) bestSpeed = dSpeed_MBps; - DISPLAY("Decompression Speed : %.1f MB/s \r", bestSpeed); + double const speed_MBps = (double)srcSize / dTime_sec / (1 MB); + if (speed_MBps > bestSpeed) bestSpeed = speed_MBps; + if (benchCompression) + DISPLAY("Compression Speed : %.1f MB/s \r", bestSpeed); + else + DISPLAY("Decompression Speed : %.1f MB/s \r", bestSpeed); + fflush(stdout); if (BMK_isCompleted_TimedFn(benchState)) break; } DISPLAY("\n"); freeDecompressInstructions(di); + freeCompressInstructions(ci); BMK_freeTimedFnState(benchState); return 0; /* success */ @@ -586,7 +720,7 @@ int bench(const char** fileNameTable, unsigned nbFiles, const char* dictionary, size_t blockSize, int clevel, unsigned nbDictMax, unsigned nbBlocks, - unsigned nbRounds) + unsigned nbRounds, int benchCompression) { int result = 0; @@ -662,25 +796,47 @@ int bench(const char** fileNameTable, unsigned nbFiles, /* now dstSlices contain the real compressed size of each block, instead of the maximum capacity */ shrinkSizes(dstSlices, cSizes); - size_t const dictMem = ZSTD_estimateDDictSize(dictBuffer.size, ZSTD_dlm_byCopy); unsigned const nbDicts = nbDictMax ? nbDictMax : nbBlocks; - size_t const allDictMem = dictMem * nbDicts; - DISPLAYLEVEL(3, "generating %u dictionaries, using %.1f MB of memory \n", - nbDicts, (double)allDictMem / (1 MB)); - ddict_collection_t const dictionaries = createDDictCollection(dictBuffer.ptr, dictBuffer.size, nbDicts); - CONTROL(dictionaries.ddicts != NULL); + cdict_collection_t const cdictionaries = createCDictCollection(dictBuffer.ptr, dictBuffer.size, nbDicts, clevel); + CONTROL(cdictionaries.cdicts != NULL); + + ddict_collection_t const ddictionaries = createDDictCollection(dictBuffer.ptr, dictBuffer.size, nbDicts); + CONTROL(ddictionaries.ddicts != NULL); + + if (benchCompression) { + size_t const dictMem = ZSTD_estimateCDictSize(dictBuffer.size, ZSTD_dlm_byCopy); + size_t const allDictMem = dictMem * nbDicts; + DISPLAYLEVEL(3, "generating %u dictionaries, using %.1f MB of memory \n", + nbDicts, (double)allDictMem / (1 MB)); + + shuffleCDictionaries(cdictionaries); + + buffer_collection_t resultCollection = createBufferCollection_fromSliceCollection(srcSlices); + CONTROL(resultCollection.buffer.ptr != NULL); - shuffleDictionaries(dictionaries); + result = benchMem(dstSlices, resultCollection.slices, ddictionaries, cdictionaries, nbRounds, benchCompression); - buffer_collection_t resultCollection = createBufferCollection_fromSliceCollectionSizes(srcSlices); - CONTROL(resultCollection.buffer.ptr != NULL); + freeBufferCollection(resultCollection); + } else { + size_t const dictMem = ZSTD_estimateDDictSize(dictBuffer.size, ZSTD_dlm_byCopy); + size_t const allDictMem = dictMem * nbDicts; + DISPLAYLEVEL(3, "generating %u dictionaries, using %.1f MB of memory \n", + nbDicts, (double)allDictMem / (1 MB)); + + shuffleDDictionaries(ddictionaries); + + buffer_collection_t resultCollection = createBufferCollection_fromSliceCollectionSizes(srcSlices); + CONTROL(resultCollection.buffer.ptr != NULL); - result = benchMem(resultCollection.slices, dstSlices, dictionaries, nbRounds); + result = benchMem(resultCollection.slices, dstSlices, ddictionaries, cdictionaries, nbRounds, benchCompression); + + freeBufferCollection(resultCollection); + } /* free all heap objects in reverse order */ - freeBufferCollection(resultCollection); - freeDDictCollection(dictionaries); + freeCDictCollection(cdictionaries); + freeDDictCollection(ddictionaries); free(cSizes); ZSTD_freeCDict(cdict); freeBuffer(dictBuffer); @@ -744,6 +900,8 @@ int usage(const char* exeName) DISPLAY (" %s [Options] filename(s) \n", exeName); DISPLAY (" \n"); DISPLAY ("Options : \n"); + DISPLAY ("-z : benchmark compression (default) \n"); + DISPLAY ("-d : benchmark decompression \n"); DISPLAY ("-r : recursively load all files in subdirectories (default: off) \n"); DISPLAY ("-B# : split input into blocks of size # (default: no split) \n"); DISPLAY ("-# : use compression level # (default: %u) \n", CLEVEL_DEFAULT); @@ -765,6 +923,7 @@ int bad_usage(const char* exeName) int main (int argc, const char** argv) { int recursiveMode = 0; + int benchCompression = 1; unsigned nbRounds = BENCH_TIME_DEFAULT_S; const char* const exeName = argv[0]; @@ -783,6 +942,8 @@ int main (int argc, const char** argv) for (int argNb = 1; argNb < argc ; argNb++) { const char* argument = argv[argNb]; if (!strcmp(argument, "-h")) { free(nameTable); return usage(exeName); } + if (!strcmp(argument, "-d")) { benchCompression = 0; continue; } + if (!strcmp(argument, "-z")) { benchCompression = 1; continue; } if (!strcmp(argument, "-r")) { recursiveMode = 1; continue; } if (!strcmp(argument, "-D")) { argNb++; assert(argNb < argc); dictionary = argv[argNb]; continue; } if (longCommandWArg(&argument, "-i")) { nbRounds = readU32FromChar(&argument); continue; } @@ -809,7 +970,7 @@ int main (int argc, const char** argv) nameTable = NULL; /* UTIL_createFileNamesTable() takes ownership of nameTable */ } - int result = bench(filenameTable->fileNames, (unsigned)filenameTable->tableSize, dictionary, blockSize, cLevel, nbDicts, nbBlocks, nbRounds); + int result = bench(filenameTable->fileNames, (unsigned)filenameTable->tableSize, dictionary, blockSize, cLevel, nbDicts, nbBlocks, nbRounds, benchCompression); UTIL_freeFileNamesTable(filenameTable); free(nameTable); From 6028827feeff8fc1630e58733a138769be84d063 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 16:07:57 -0400 Subject: [PATCH 321/402] Rewrite Include Paths to be Relative Addresses #1998. --- lib/Makefile | 4 ++-- lib/common/pool.h | 2 +- lib/common/zstd_internal.h | 2 +- lib/compress/fse_compress.c | 12 ++++++------ lib/compress/hist.c | 6 +++--- lib/compress/huf_compress.c | 10 +++++----- lib/compress/zstd_compress.c | 10 +++++----- lib/compress/zstd_compress_internal.h | 2 +- lib/compress/zstd_compress_sequences.h | 4 ++-- lib/compress/zstd_compress_superblock.c | 7 ++++--- lib/compress/zstd_compress_superblock.h | 2 +- lib/compress/zstd_cwksp.h | 2 +- lib/compress/zstd_double_fast.h | 2 +- lib/compress/zstd_fast.h | 2 +- lib/compress/zstd_ldm.c | 2 +- lib/compress/zstd_ldm.h | 2 +- lib/compress/zstdmt_compress.c | 6 +++--- lib/compress/zstdmt_compress.h | 2 +- lib/decompress/huf_decompress.c | 10 +++++----- lib/decompress/zstd_ddict.c | 10 +++++----- lib/decompress/zstd_ddict.h | 2 +- lib/decompress/zstd_decompress.c | 12 ++++++------ lib/decompress/zstd_decompress_block.c | 12 ++++++------ lib/decompress/zstd_decompress_block.h | 4 ++-- lib/decompress/zstd_decompress_internal.h | 4 ++-- lib/deprecated/zbuff.h | 4 ++-- lib/deprecated/zbuff_common.c | 2 +- lib/dictBuilder/cover.c | 8 ++++---- lib/dictBuilder/cover.h | 8 ++++---- lib/dictBuilder/fastcover.c | 8 ++++---- lib/dictBuilder/zdict.c | 12 ++++++------ lib/legacy/zstd_legacy.h | 6 +++--- lib/legacy/zstd_v01.c | 2 +- lib/legacy/zstd_v02.c | 2 +- lib/legacy/zstd_v03.c | 2 +- lib/legacy/zstd_v04.c | 2 +- lib/legacy/zstd_v05.c | 2 +- lib/legacy/zstd_v05.h | 2 +- lib/legacy/zstd_v06.c | 2 +- lib/legacy/zstd_v07.c | 4 ++-- 40 files changed, 100 insertions(+), 99 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index ac38867a931..888db2114b9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -20,7 +20,7 @@ LIBVER := $(shell echo $(LIBVER_SCRIPT)) VERSION?= $(LIBVER) CCVER := $(shell $(CC) --version) -CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_ +CPPFLAGS+= -DXXH_NAMESPACE=ZSTD_ ifeq ($(OS),Windows_NT) # MinGW assumed CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting endif @@ -122,7 +122,7 @@ ifneq ($(ZSTD_LEGACY_SUPPORT), 0) ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0) ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]') endif - CPPFLAGS += -I./legacy + CPPFLAGS += endif CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) diff --git a/lib/common/pool.h b/lib/common/pool.h index 8503e2d2309..259bafc9757 100644 --- a/lib/common/pool.h +++ b/lib/common/pool.h @@ -18,7 +18,7 @@ extern "C" { #include /* size_t */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */ -#include "zstd.h" +#include "../zstd.h" typedef struct POOL_ctx_s POOL_ctx; diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 57a6137e154..bd08de82120 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -24,7 +24,7 @@ #include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ #include "error_private.h" #define ZSTD_STATIC_LINKING_ONLY -#include "zstd.h" +#include "../zstd.h" #define FSE_STATIC_LINKING_ONLY #include "fse.h" #define HUF_STATIC_LINKING_ONLY diff --git a/lib/compress/fse_compress.c b/lib/compress/fse_compress.c index e09b646df11..a42759814fd 100644 --- a/lib/compress/fse_compress.c +++ b/lib/compress/fse_compress.c @@ -17,14 +17,14 @@ ****************************************************************/ #include /* malloc, free, qsort */ #include /* memcpy, memset */ -#include "compiler.h" -#include "mem.h" /* U32, U16, etc. */ -#include "debug.h" /* assert, DEBUGLOG */ +#include "../common/compiler.h" +#include "../common/mem.h" /* U32, U16, etc. */ +#include "../common/debug.h" /* assert, DEBUGLOG */ #include "hist.h" /* HIST_count_wksp */ -#include "bitstream.h" +#include "../common/bitstream.h" #define FSE_STATIC_LINKING_ONLY -#include "fse.h" -#include "error_private.h" +#include "../common/fse.h" +#include "../common/error_private.h" /* ************************************************************** diff --git a/lib/compress/hist.c b/lib/compress/hist.c index c17b9725f0d..61e08c7968b 100644 --- a/lib/compress/hist.c +++ b/lib/compress/hist.c @@ -14,9 +14,9 @@ ****************************************************************** */ /* --- dependencies --- */ -#include "mem.h" /* U32, BYTE, etc. */ -#include "debug.h" /* assert, DEBUGLOG */ -#include "error_private.h" /* ERROR */ +#include "../common/mem.h" /* U32, BYTE, etc. */ +#include "../common/debug.h" /* assert, DEBUGLOG */ +#include "../common/error_private.h" /* ERROR */ #include "hist.h" diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 533f7cb25d0..16a38e36c86 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -25,14 +25,14 @@ ****************************************************************/ #include /* memcpy, memset */ #include /* printf (debug) */ -#include "compiler.h" -#include "bitstream.h" +#include "../common/compiler.h" +#include "../common/bitstream.h" #include "hist.h" #define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */ -#include "fse.h" /* header compression */ +#include "../common/fse.h" /* header compression */ #define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "error_private.h" +#include "../common/huf.h" +#include "../common/error_private.h" /* ************************************************************** diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 22f5542eb08..ff8a00e6b3b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -13,13 +13,13 @@ ***************************************/ #include /* INT_MAX */ #include /* memset */ -#include "cpu.h" -#include "mem.h" -#include "hist.h" /* HIST_countFast_wksp */ +#include "../common/cpu.h" +#include "../common/mem.h" +#include "hist.h" /* HIST_countFast_wksp */ #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ -#include "fse.h" +#include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY -#include "huf.h" +#include "../common/huf.h" #include "zstd_compress_internal.h" #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index d95eb1bf90d..8a16c371a69 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -18,7 +18,7 @@ /*-************************************* * Dependencies ***************************************/ -#include "zstd_internal.h" +#include "../common/zstd_internal.h" #include "zstd_cwksp.h" #ifdef ZSTD_MULTITHREAD # include "zstdmt_compress.h" diff --git a/lib/compress/zstd_compress_sequences.h b/lib/compress/zstd_compress_sequences.h index b884e45b42e..68c6f9a5acd 100644 --- a/lib/compress/zstd_compress_sequences.h +++ b/lib/compress/zstd_compress_sequences.h @@ -11,8 +11,8 @@ #ifndef ZSTD_COMPRESS_SEQUENCES_H #define ZSTD_COMPRESS_SEQUENCES_H -#include "fse.h" /* FSE_repeat, FSE_CTable */ -#include "zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ +#include "../common/fse.h" /* FSE_repeat, FSE_CTable */ +#include "../common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ typedef enum { ZSTD_defaultDisallowed = 0, diff --git a/lib/compress/zstd_compress_superblock.c b/lib/compress/zstd_compress_superblock.c index e44a14b621a..b693866c0ac 100644 --- a/lib/compress/zstd_compress_superblock.c +++ b/lib/compress/zstd_compress_superblock.c @@ -11,12 +11,13 @@ /*-************************************* * Dependencies ***************************************/ -#include "hist.h" /* HIST_countFast_wksp */ +#include "zstd_compress_superblock.h" + +#include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */ +#include "hist.h" /* HIST_countFast_wksp */ #include "zstd_compress_internal.h" #include "zstd_compress_sequences.h" #include "zstd_compress_literals.h" -#include "zstd_compress_superblock.h" -#include "zstd_internal.h" /* ZSTD_getSequenceLength */ /*-************************************* * Superblock entropy buffer structs diff --git a/lib/compress/zstd_compress_superblock.h b/lib/compress/zstd_compress_superblock.h index 35d207299d8..07f4cb1dc64 100644 --- a/lib/compress/zstd_compress_superblock.h +++ b/lib/compress/zstd_compress_superblock.h @@ -15,7 +15,7 @@ * Dependencies ***************************************/ -#include "zstd.h" /* ZSTD_CCtx */ +#include "../zstd.h" /* ZSTD_CCtx */ /*-************************************* * Target Compressed Block Size diff --git a/lib/compress/zstd_cwksp.h b/lib/compress/zstd_cwksp.h index 91f812fa310..a25c9263b7d 100644 --- a/lib/compress/zstd_cwksp.h +++ b/lib/compress/zstd_cwksp.h @@ -14,7 +14,7 @@ /*-************************************* * Dependencies ***************************************/ -#include "zstd_internal.h" +#include "../common/zstd_internal.h" #if defined (__cplusplus) extern "C" { diff --git a/lib/compress/zstd_double_fast.h b/lib/compress/zstd_double_fast.h index 73a2002f3a3..14d944d69bc 100644 --- a/lib/compress/zstd_double_fast.h +++ b/lib/compress/zstd_double_fast.h @@ -15,7 +15,7 @@ extern "C" { #endif -#include "mem.h" /* U32 */ +#include "../common/mem.h" /* U32 */ #include "zstd_compress_internal.h" /* ZSTD_CCtx, size_t */ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, diff --git a/lib/compress/zstd_fast.h b/lib/compress/zstd_fast.h index 3e15cc85cdd..cf6aaa8e675 100644 --- a/lib/compress/zstd_fast.h +++ b/lib/compress/zstd_fast.h @@ -15,7 +15,7 @@ extern "C" { #endif -#include "mem.h" /* U32 */ +#include "../common/mem.h" /* U32 */ #include "zstd_compress_internal.h" void ZSTD_fillHashTable(ZSTD_matchState_t* ms, diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 0e72c0b5986..2a1c2cd6287 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -10,7 +10,7 @@ #include "zstd_ldm.h" -#include "debug.h" +#include "../common/debug.h" #include "zstd_fast.h" /* ZSTD_fillHashTable() */ #include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */ diff --git a/lib/compress/zstd_ldm.h b/lib/compress/zstd_ldm.h index aa2b6c52ec8..229ea05a9e1 100644 --- a/lib/compress/zstd_ldm.h +++ b/lib/compress/zstd_ldm.h @@ -16,7 +16,7 @@ extern "C" { #endif #include "zstd_compress_internal.h" /* ldmParams_t, U32 */ -#include "zstd.h" /* ZSTD_CCtx, size_t */ +#include "../zstd.h" /* ZSTD_CCtx, size_t */ /*-************************************* * Long distance matching diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 56186f506dc..f6b26a757fa 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -22,9 +22,9 @@ /* ====== Dependencies ====== */ #include /* memcpy, memset */ #include /* INT_MAX, UINT_MAX */ -#include "mem.h" /* MEM_STATIC */ -#include "pool.h" /* threadpool */ -#include "threading.h" /* mutex */ +#include "../common/mem.h" /* MEM_STATIC */ +#include "../common/pool.h" /* threadpool */ +#include "../common/threading.h" /* mutex */ #include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */ #include "zstd_ldm.h" #include "zstdmt_compress.h" diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index b90fd389a41..89914eb7f88 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -40,7 +40,7 @@ /* === Dependencies === */ #include /* size_t */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */ -#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */ +#include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */ /* === Constants === */ diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index ab5db481c36..68293a13096 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -16,12 +16,12 @@ * Dependencies ****************************************************************/ #include /* memcpy, memset */ -#include "compiler.h" -#include "bitstream.h" /* BIT_* */ -#include "fse.h" /* to compress headers */ +#include "../common/compiler.h" +#include "../common/bitstream.h" /* BIT_* */ +#include "../common/fse.h" /* to compress headers */ #define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "error_private.h" +#include "../common/huf.h" +#include "../common/error_private.h" /* ************************************************************** * Macros diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index 70477ca7d7b..042a7bc855c 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -15,17 +15,17 @@ * Dependencies *********************************************************/ #include /* memcpy, memmove, memset */ -#include "cpu.h" /* bmi2 */ -#include "mem.h" /* low level memory routines */ +#include "../common/cpu.h" /* bmi2 */ +#include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY -#include "fse.h" +#include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY -#include "huf.h" +#include "../common/huf.h" #include "zstd_decompress_internal.h" #include "zstd_ddict.h" #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) -# include "zstd_legacy.h" +# include "../legacy/zstd_legacy.h" #endif diff --git a/lib/decompress/zstd_ddict.h b/lib/decompress/zstd_ddict.h index 3ab7532ee3e..af307efd3d7 100644 --- a/lib/decompress/zstd_ddict.h +++ b/lib/decompress/zstd_ddict.h @@ -16,7 +16,7 @@ * Dependencies *********************************************************/ #include /* size_t */ -#include "zstd.h" /* ZSTD_DDict, and several public functions */ +#include "../zstd.h" /* ZSTD_DDict, and several public functions */ /*-******************************************************* diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 91adb8a6efe..90ddeaabe18 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -56,19 +56,19 @@ * Dependencies *********************************************************/ #include /* memcpy, memmove, memset */ -#include "cpu.h" /* bmi2 */ -#include "mem.h" /* low level memory routines */ +#include "../common/cpu.h" /* bmi2 */ +#include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY -#include "fse.h" +#include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "zstd_internal.h" /* blockProperties_t */ +#include "../common/huf.h" +#include "../common/zstd_internal.h" /* blockProperties_t */ #include "zstd_decompress_internal.h" /* ZSTD_DCtx */ #include "zstd_ddict.h" /* ZSTD_DDictDictContent */ #include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */ #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) -# include "zstd_legacy.h" +# include "../legacy/zstd_legacy.h" #endif diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 5a1226ebae7..6eb7462cd10 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -15,14 +15,14 @@ * Dependencies *********************************************************/ #include /* memcpy, memmove, memset */ -#include "compiler.h" /* prefetch */ -#include "cpu.h" /* bmi2 */ -#include "mem.h" /* low level memory routines */ +#include "../common/compiler.h" /* prefetch */ +#include "../common/cpu.h" /* bmi2 */ +#include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY -#include "fse.h" +#include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "zstd_internal.h" +#include "../common/huf.h" +#include "../common/zstd_internal.h" #include "zstd_decompress_internal.h" /* ZSTD_DCtx */ #include "zstd_ddict.h" /* ZSTD_DDictDictContent */ #include "zstd_decompress_block.h" diff --git a/lib/decompress/zstd_decompress_block.h b/lib/decompress/zstd_decompress_block.h index a065f8d930a..bf39b7350cf 100644 --- a/lib/decompress/zstd_decompress_block.h +++ b/lib/decompress/zstd_decompress_block.h @@ -16,8 +16,8 @@ * Dependencies *********************************************************/ #include /* size_t */ -#include "zstd.h" /* DCtx, and some public functions */ -#include "zstd_internal.h" /* blockProperties_t, and some public functions */ +#include "../zstd.h" /* DCtx, and some public functions */ +#include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */ #include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */ diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index f1c2585a662..8c4f79f465d 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -19,8 +19,8 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include "mem.h" /* BYTE, U16, U32 */ -#include "zstd_internal.h" /* ZSTD_seqSymbol */ +#include "../common/mem.h" /* BYTE, U16, U32 */ +#include "../common/zstd_internal.h" /* ZSTD_seqSymbol */ diff --git a/lib/deprecated/zbuff.h b/lib/deprecated/zbuff.h index 7686f76a46a..03cb14a039d 100644 --- a/lib/deprecated/zbuff.h +++ b/lib/deprecated/zbuff.h @@ -28,7 +28,7 @@ extern "C" { * Dependencies ***************************************/ #include /* size_t */ -#include "zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */ +#include "../zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */ /* *************************************************************** @@ -186,7 +186,7 @@ ZBUFF_DEPRECATED("use ZSTD_DStreamOutSize") size_t ZBUFF_recommendedDOutSize(voi /*--- Dependency ---*/ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_customMem */ -#include "zstd.h" +#include "../zstd.h" /*--- Custom memory allocator ---*/ diff --git a/lib/deprecated/zbuff_common.c b/lib/deprecated/zbuff_common.c index e2b9613f062..579bc4df14a 100644 --- a/lib/deprecated/zbuff_common.c +++ b/lib/deprecated/zbuff_common.c @@ -11,7 +11,7 @@ /*-************************************* * Dependencies ***************************************/ -#include "error_private.h" +#include "../common/error_private.h" #include "zbuff.h" /*-**************************************** diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index b57981c52b2..da54ef15f2b 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -26,11 +26,11 @@ #include /* memset */ #include /* clock */ -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" +#include "../common/mem.h" /* read */ +#include "../common/pool.h" +#include "../common/threading.h" #include "cover.h" -#include "zstd_internal.h" /* includes zstd.h */ +#include "../common/zstd_internal.h" /* includes zstd.h */ #ifndef ZDICT_STATIC_LINKING_ONLY #define ZDICT_STATIC_LINKING_ONLY #endif diff --git a/lib/dictBuilder/cover.h b/lib/dictBuilder/cover.h index 77943f0a715..f2aa0e35e3a 100644 --- a/lib/dictBuilder/cover.h +++ b/lib/dictBuilder/cover.h @@ -12,10 +12,10 @@ #include /* malloc, free, qsort */ #include /* memset */ #include /* clock */ -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" -#include "zstd_internal.h" /* includes zstd.h */ +#include "../common/mem.h" /* read */ +#include "../common/pool.h" +#include "../common/threading.h" +#include "../common/zstd_internal.h" /* includes zstd.h */ #ifndef ZDICT_STATIC_LINKING_ONLY #define ZDICT_STATIC_LINKING_ONLY #endif diff --git a/lib/dictBuilder/fastcover.c b/lib/dictBuilder/fastcover.c index 5bc9ca50fc2..485c333b54a 100644 --- a/lib/dictBuilder/fastcover.c +++ b/lib/dictBuilder/fastcover.c @@ -16,11 +16,11 @@ #include /* memset */ #include /* clock */ -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" +#include "../common/mem.h" /* read */ +#include "../common/pool.h" +#include "../common/threading.h" #include "cover.h" -#include "zstd_internal.h" /* includes zstd.h */ +#include "../common/zstd_internal.h" /* includes zstd.h */ #ifndef ZDICT_STATIC_LINKING_ONLY #define ZDICT_STATIC_LINKING_ONLY #endif diff --git a/lib/dictBuilder/zdict.c b/lib/dictBuilder/zdict.c index 6fa1ca69910..6d0b04231bb 100644 --- a/lib/dictBuilder/zdict.c +++ b/lib/dictBuilder/zdict.c @@ -37,18 +37,18 @@ #include /* fprintf, fopen, ftello64 */ #include /* clock */ -#include "mem.h" /* read */ -#include "fse.h" /* FSE_normalizeCount, FSE_writeNCount */ +#include "../common/mem.h" /* read */ +#include "../common/fse.h" /* FSE_normalizeCount, FSE_writeNCount */ #define HUF_STATIC_LINKING_ONLY -#include "huf.h" /* HUF_buildCTable, HUF_writeCTable */ -#include "zstd_internal.h" /* includes zstd.h */ -#include "xxhash.h" /* XXH64 */ +#include "../common/huf.h" /* HUF_buildCTable, HUF_writeCTable */ +#include "../common/zstd_internal.h" /* includes zstd.h */ +#include "../common/xxhash.h" /* XXH64 */ #include "divsufsort.h" #ifndef ZDICT_STATIC_LINKING_ONLY # define ZDICT_STATIC_LINKING_ONLY #endif #include "zdict.h" -#include "compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */ +#include "../compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */ /*-************************************* diff --git a/lib/legacy/zstd_legacy.h b/lib/legacy/zstd_legacy.h index ecd968212eb..6bea6a519ab 100644 --- a/lib/legacy/zstd_legacy.h +++ b/lib/legacy/zstd_legacy.h @@ -18,9 +18,9 @@ extern "C" { /* ************************************* * Includes ***************************************/ -#include "mem.h" /* MEM_STATIC */ -#include "error_private.h" /* ERROR */ -#include "zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */ +#include "../common/mem.h" /* MEM_STATIC */ +#include "../common/error_private.h" /* ERROR */ +#include "../common/zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */ #if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0) # undef ZSTD_LEGACY_SUPPORT diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index 4d5ecf7d324..0517222ca5c 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -14,7 +14,7 @@ ******************************************/ #include /* size_t, ptrdiff_t */ #include "zstd_v01.h" -#include "error_private.h" +#include "../common/error_private.h" /****************************************** diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index 7105aa49a6b..a7aa27cdfe2 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -11,7 +11,7 @@ #include /* size_t, ptrdiff_t */ #include "zstd_v02.h" -#include "error_private.h" +#include "../common/error_private.h" /****************************************** diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 980cf02f1c9..1b00c98bfea 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -11,7 +11,7 @@ #include /* size_t, ptrdiff_t */ #include "zstd_v03.h" -#include "error_private.h" +#include "../common/error_private.h" /****************************************** diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index e5b51f7823e..1a3d49cf694 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -16,7 +16,7 @@ #include /* memcpy */ #include "zstd_v04.h" -#include "error_private.h" +#include "../common/error_private.h" /* ****************************************************************** diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 649144d0438..79ea59a1b84 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -11,7 +11,7 @@ /*- Dependencies -*/ #include "zstd_v05.h" -#include "error_private.h" +#include "../common/error_private.h" /* ****************************************************************** diff --git a/lib/legacy/zstd_v05.h b/lib/legacy/zstd_v05.h index 6c46e8f23aa..167d892e665 100644 --- a/lib/legacy/zstd_v05.h +++ b/lib/legacy/zstd_v05.h @@ -19,7 +19,7 @@ extern "C" { * Dependencies ***************************************/ #include /* size_t */ -#include "mem.h" /* U64, U32 */ +#include "../common/mem.h" /* U64, U32 */ /* ************************************* diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 288eebe8177..1a670fad0fb 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -14,7 +14,7 @@ #include /* size_t, ptrdiff_t */ #include /* memcpy */ #include /* malloc, free, qsort */ -#include "error_private.h" +#include "../common/error_private.h" diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index 36593d38b5b..5393475dad0 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -17,14 +17,14 @@ #ifndef XXH_STATIC_LINKING_ONLY # define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ #endif -#include "xxhash.h" /* XXH64_* */ +#include "../common/xxhash.h" /* XXH64_* */ #include "zstd_v07.h" #define FSEv07_STATIC_LINKING_ONLY /* FSEv07_MIN_TABLELOG */ #define HUFv07_STATIC_LINKING_ONLY /* HUFv07_TABLELOG_ABSOLUTEMAX */ #define ZSTDv07_STATIC_LINKING_ONLY -#include "error_private.h" +#include "../common/error_private.h" #ifdef ZSTDv07_STATIC_LINKING_ONLY From 7dcca6bc64feff4bb02055fdf9a1f8e3ac6fbb96 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 16:20:40 -0400 Subject: [PATCH 322/402] Also Move programs/ Directory to Relative Includes --- programs/Makefile | 5 +---- programs/benchzstd.c | 8 ++++---- programs/benchzstd.h | 2 +- programs/datagen.c | 2 +- programs/dibio.c | 4 ++-- programs/dibio.h | 2 +- programs/fileio.c | 8 ++++---- programs/fileio.h | 2 +- programs/util.h | 2 +- programs/zstdcli.c | 2 +- 10 files changed, 17 insertions(+), 20 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index abad6da6b96..1a85f185e5c 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -43,9 +43,7 @@ else ALIGN_LOOP = endif -CPPFLAGS+= -I$(ZSTDDIR) -I$(ZSTDDIR)/common -I$(ZSTDDIR)/compress \ - -I$(ZSTDDIR)/dictBuilder \ - -DXXH_NAMESPACE=ZSTD_ +CPPFLAGS+= -DXXH_NAMESPACE=ZSTD_ ifeq ($(OS),Windows_NT) # MinGW assumed CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting endif @@ -72,7 +70,6 @@ ifneq ($(ZSTD_LEGACY_SUPPORT), 0) ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0) ZSTDLEGACY_FILES += $(shell ls $(ZSTDDIR)/legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]') endif - CPPFLAGS += -I$(ZSTDDIR)/legacy else endif diff --git a/programs/benchzstd.c b/programs/benchzstd.c index 80e98050c7f..77056203d55 100644 --- a/programs/benchzstd.c +++ b/programs/benchzstd.c @@ -30,13 +30,13 @@ #include "timefn.h" /* UTIL_time_t */ #include "benchfn.h" -#include "mem.h" +#include "../lib/common/mem.h" #define ZSTD_STATIC_LINKING_ONLY -#include "zstd.h" +#include "../lib/zstd.h" #include "datagen.h" /* RDG_genBuffer */ -#include "xxhash.h" +#include "../lib/common/xxhash.h" #include "benchzstd.h" -#include "zstd_errors.h" +#include "../lib/common/zstd_errors.h" /* ************************************* diff --git a/programs/benchzstd.h b/programs/benchzstd.h index 99fae56a01a..8c55b3c4f29 100644 --- a/programs/benchzstd.h +++ b/programs/benchzstd.h @@ -24,7 +24,7 @@ extern "C" { /* === Dependencies === */ #include /* size_t */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */ -#include "zstd.h" /* ZSTD_compressionParameters */ +#include "../lib/zstd.h" /* ZSTD_compressionParameters */ /* === Constants === */ diff --git a/programs/datagen.c b/programs/datagen.c index 7cf83bdaa4a..4353b7ff994 100644 --- a/programs/datagen.c +++ b/programs/datagen.c @@ -18,7 +18,7 @@ #include /* malloc, free */ #include /* FILE, fwrite, fprintf */ #include /* memcpy */ -#include "mem.h" /* U32 */ +#include "../lib/common/mem.h" /* U32 */ /*-************************************ diff --git a/programs/dibio.c b/programs/dibio.c index 2b322b639cc..463095a8e81 100644 --- a/programs/dibio.c +++ b/programs/dibio.c @@ -30,8 +30,8 @@ #include #include "timefn.h" /* UTIL_time_t, UTIL_clockSpanMicro, UTIL_getTime */ -#include "mem.h" /* read */ -#include "error_private.h" +#include "../lib/common/mem.h" /* read */ +#include "../lib/common/error_private.h" #include "dibio.h" diff --git a/programs/dibio.h b/programs/dibio.h index 436bddbb503..682723d6a54 100644 --- a/programs/dibio.h +++ b/programs/dibio.h @@ -19,7 +19,7 @@ * Dependencies ***************************************/ #define ZDICT_STATIC_LINKING_ONLY -#include "zdict.h" /* ZDICT_params_t */ +#include "../lib/dictBuilder/zdict.h" /* ZDICT_params_t */ /*-************************************* diff --git a/programs/fileio.c b/programs/fileio.c index 802e6fb61c7..d72879d64ea 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -39,13 +39,13 @@ # include #endif -#include "mem.h" /* U32, U64 */ +#include "../lib/common/mem.h" /* U32, U64 */ #include "fileio.h" #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_magicNumber, ZSTD_frameHeaderSize_max */ -#include "zstd.h" -#include "zstd_errors.h" /* ZSTD_error_frameParameter_windowTooLarge */ -#include "zstd_compress_internal.h" +#include "../lib/zstd.h" +#include "../lib/common/zstd_errors.h" /* ZSTD_error_frameParameter_windowTooLarge */ +#include "../lib/compress/zstd_compress_internal.h" #if defined(ZSTD_GZCOMPRESS) || defined(ZSTD_GZDECOMPRESS) # include diff --git a/programs/fileio.h b/programs/fileio.h index 565cbae117c..2fbf01f8282 100644 --- a/programs/fileio.h +++ b/programs/fileio.h @@ -13,7 +13,7 @@ #define FILEIO_H_23981798732 #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */ -#include "zstd.h" /* ZSTD_* */ +#include "../lib/zstd.h" /* ZSTD_* */ #if defined (__cplusplus) extern "C" { diff --git a/programs/util.h b/programs/util.h index 40200729adb..8e187e4f299 100644 --- a/programs/util.h +++ b/programs/util.h @@ -23,7 +23,7 @@ extern "C" { #include /* size_t, ptrdiff_t */ #include /* stat, utime */ #include /* stat, chmod */ -#include "mem.h" /* U64 */ +#include "../lib/common/mem.h" /* U64 */ /*-************************************************************ diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 3e293c57b7b..81f1910c202 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -40,7 +40,7 @@ #ifndef ZSTD_NODICT # include "dibio.h" /* ZDICT_cover_params_t, DiB_trainFromFiles() */ #endif -#include "zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ +#include "../lib/zstd.h" /* ZSTD_VERSION_STRING, ZSTD_minCLevel, ZSTD_maxCLevel */ /*-************************************ From 7b75d772b1dc94c909d79f3c0b411d47f7a920ed Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 16:33:51 -0400 Subject: [PATCH 323/402] Remove Useless Assignment in Makefile --- lib/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Makefile b/lib/Makefile index 888db2114b9..773b20c61f9 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -122,7 +122,6 @@ ifneq ($(ZSTD_LEGACY_SUPPORT), 0) ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0) ZSTD_FILES += $(shell ls legacy/*.c | $(GREP) 'v0[$(ZSTD_LEGACY_SUPPORT)-7]') endif - CPPFLAGS += endif CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT) From b48f6c7d26722d80f117ae2df8410b00eee9ca59 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 1 May 2020 17:56:51 -0400 Subject: [PATCH 324/402] Try to Fix Single File Library Combiner Script to Handle Relative Includes --- contrib/single_file_libs/combine.sh | 38 ++++++++----- .../create_single_file_decoder.sh | 2 +- .../create_single_file_library.sh | 2 +- contrib/single_file_libs/zstd-in.c | 53 +++++++++---------- contrib/single_file_libs/zstddeclib-in.c | 22 ++++---- 5 files changed, 63 insertions(+), 54 deletions(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index ea99717f87c..a98eef28396 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -66,33 +66,43 @@ write_line() { fi } -# Adds the contents of $1 with any of its includes inlined -add_file() { - # Match the path - local file= - for root in $ROOTS; do - if [ -f "$root/$1" ]; then - file="$root/$1" +# Find this file! +resolve_include() { + local srcdir=$1 + local inc=$2 + for root in $srcdir $ROOTS; do + if [ -f "$root/$inc" ]; then + echo "$(realpath --relative-to . "$root/$inc")" + return 0 fi done + return 1 +} + +# Adds the contents of $1 with any of its includes inlined +add_file() { + local file=$1 if [ -n "$file" ]; then if [ -n "$DESTN" ]; then # Log but only if not writing to stdout echo "Processing: $file" fi + # Get directory to resolve relative includes + local srcdir="$(dirname "$file")" # Read the file local line= while IFS= read -r line; do if echo "$line" | grep -Eq '^\s*#\s*include\s*".+"'; then # We have an include directive so strip the (first) file - local inc=$(echo "$line" | grep -Eo '".*"' | grep -Eo '\w*(\.?\w+)+' | head -1) + local inc=$(echo "$line" | grep -Eo '".*"' | sed 's/"\([^"]\+\)"/\1/' | head -1) + local res_inc="$(resolve_include "$srcdir" "$inc")" if list_has_item "$XINCS" "$inc"; then # The file was excluded so error if the source attempts to use it write_line "#error Using excluded file: $inc" else - if ! list_has_item "$FOUND" "$inc"; then + if ! list_has_item "$FOUND" "$res_inc"; then # The file was not previously encountered - FOUND="$FOUND $inc" + FOUND="$FOUND $res_inc" if list_has_item "$KINCS" "$inc"; then # But the include was flagged to keep as included write_line "/**** *NOT* inlining $inc ****/" @@ -100,7 +110,7 @@ add_file() { else # The file was neither excluded nor seen before so inline it write_line "/**** start inlining $inc ****/" - add_file "$inc" + add_file "$res_inc" write_line "/**** ended inlining $inc ****/" fi else @@ -122,6 +132,10 @@ add_file() { done < "$file" else write_line "#error Unable to find \"$1\"" + if [ -n "$DESTN" ]; then + # Log but only if not writing to stdout + echo "Error: Unable to find: \"$1\"" + fi fi } @@ -155,7 +169,7 @@ if [ -n "$1" ]; then printf "" > "$DESTN" fi test_grep - add_file $1 + add_file "$1" else echo "Input file not found: \"$1\"" exit 1 diff --git a/contrib/single_file_libs/create_single_file_decoder.sh b/contrib/single_file_libs/create_single_file_decoder.sh index ad249ccd799..b5f5613ae2e 100755 --- a/contrib/single_file_libs/create_single_file_decoder.sh +++ b/contrib/single_file_libs/create_single_file_decoder.sh @@ -5,7 +5,7 @@ ZSTD_SRC_ROOT="../../lib" # Amalgamate the sources echo "Amalgamating files... this can take a while" -./combine.sh -r "$ZSTD_SRC_ROOT" -r "$ZSTD_SRC_ROOT/common" -r "$ZSTD_SRC_ROOT/decompress" -o zstddeclib.c zstddeclib-in.c +./combine.sh -r "$ZSTD_SRC_ROOT" -o zstddeclib.c zstddeclib-in.c # Did combining work? if [ $? -ne 0 ]; then echo "Combine script: FAILED" diff --git a/contrib/single_file_libs/create_single_file_library.sh b/contrib/single_file_libs/create_single_file_library.sh index 68bbfbd2729..6cbff459577 100755 --- a/contrib/single_file_libs/create_single_file_library.sh +++ b/contrib/single_file_libs/create_single_file_library.sh @@ -5,7 +5,7 @@ ZSTD_SRC_ROOT="../../lib" # Amalgamate the sources echo "Amalgamating files... this can take a while" -./combine.sh -r "$ZSTD_SRC_ROOT" -r "$ZSTD_SRC_ROOT/common" -r "$ZSTD_SRC_ROOT/compress" -r "$ZSTD_SRC_ROOT/decompress" -k zstd.h -o zstd.c zstd-in.c +./combine.sh -r "$ZSTD_SRC_ROOT" -k zstd.h -o zstd.c zstd-in.c # Did combining work? if [ $? -ne 0 ]; then echo "Combine script: FAILED" diff --git a/contrib/single_file_libs/zstd-in.c b/contrib/single_file_libs/zstd-in.c index c3551226411..aa197a682c0 100644 --- a/contrib/single_file_libs/zstd-in.c +++ b/contrib/single_file_libs/zstd-in.c @@ -4,7 +4,7 @@ * * Generate using: * \code - * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/compress -r ../../lib/decompress -k zstd.h -o zstd.c zstd-in.c + * combine.sh -r ../../lib -k zstd.h -o zstd.c zstd-in.c * \endcode */ /* @@ -46,34 +46,31 @@ #define ZSTD_MULTITHREAD #endif -/* lib/common */ -#include "debug.c" -#include "entropy_common.c" -#include "error_private.c" -#include "fse_decompress.c" -#include "threading.c" -#include "pool.c" -#include "zstd_common.c" +#include "common/debug.c" +#include "common/entropy_common.c" +#include "common/error_private.c" +#include "common/fse_decompress.c" +#include "common/threading.c" +#include "common/pool.c" +#include "common/zstd_common.c" -/* lib/compress */ -#include "fse_compress.c" -#include "hist.c" -#include "huf_compress.c" -#include "zstd_compress_literals.c" -#include "zstd_compress_sequences.c" -#include "zstd_compress_superblock.c" -#include "zstd_compress.c" -#include "zstd_double_fast.c" -#include "zstd_fast.c" -#include "zstd_lazy.c" -#include "zstd_ldm.c" -#include "zstd_opt.c" +#include "compress/fse_compress.c" +#include "compress/hist.c" +#include "compress/huf_compress.c" +#include "compress/zstd_compress_literals.c" +#include "compress/zstd_compress_sequences.c" +#include "compress/zstd_compress_superblock.c" +#include "compress/zstd_compress.c" +#include "compress/zstd_double_fast.c" +#include "compress/zstd_fast.c" +#include "compress/zstd_lazy.c" +#include "compress/zstd_ldm.c" +#include "compress/zstd_opt.c" #ifdef ZSTD_MULTITHREAD -#include "zstdmt_compress.c" +#include "compress/zstdmt_compress.c" #endif -/* lib/decompress */ -#include "huf_decompress.c" -#include "zstd_ddict.c" -#include "zstd_decompress.c" -#include "zstd_decompress_block.c" +#include "decompress/huf_decompress.c" +#include "decompress/zstd_ddict.c" +#include "decompress/zstd_decompress.c" +#include "decompress/zstd_decompress_block.c" diff --git a/contrib/single_file_libs/zstddeclib-in.c b/contrib/single_file_libs/zstddeclib-in.c index c447bc25ca3..a9083dd34b5 100755 --- a/contrib/single_file_libs/zstddeclib-in.c +++ b/contrib/single_file_libs/zstddeclib-in.c @@ -4,7 +4,7 @@ * * Generate using: * \code - * combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c + * combine.sh -r ../../lib -o zstddeclib.c zstddeclib-in.c * \endcode */ /* @@ -42,15 +42,13 @@ #define ZSTD_NOBENCH #define ZSTD_STRIP_ERROR_STRINGS -/* lib/common */ -#include "debug.c" -#include "entropy_common.c" -#include "error_private.c" -#include "fse_decompress.c" -#include "zstd_common.c" +#include "common/debug.c" +#include "common/entropy_common.c" +#include "common/error_private.c" +#include "common/fse_decompress.c" +#include "common/zstd_common.c" -/* lib/decompress */ -#include "huf_decompress.c" -#include "zstd_ddict.c" -#include "zstd_decompress.c" -#include "zstd_decompress_block.c" +#include "decompress/huf_decompress.c" +#include "decompress/zstd_ddict.c" +#include "decompress/zstd_decompress.c" +#include "decompress/zstd_decompress_block.c" From c1b836f4c3aa3af0139eb8ae28622dde7ccfbe7a Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 4 May 2020 14:43:09 -0700 Subject: [PATCH 325/402] fix minor conversion warnings --- lib/compress/huf_compress.c | 48 +++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 533f7cb25d0..a6c871a5e69 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -88,18 +88,18 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); /* Write table description header */ - { CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); + { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); op += hSize; } /* Compress */ CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) ); + { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; } - return op-ostart; + return (size_t)(op-ostart); } @@ -220,7 +220,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* there are several too large elements (at least >= 2) */ { int totalCost = 0; const U32 baseCost = 1 << (largestBits - maxNbBits); - U32 n = lastNonNull; + int n = (int)lastNonNull; while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); @@ -235,22 +235,22 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* repay normalized cost */ { U32 const noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_TABLELOG_MAX+2]; - int pos; /* Get pos of last (smallest) symbol per rank */ memset(rankLast, 0xF0, sizeof(rankLast)); { U32 currentNbBits = maxNbBits; + int pos; for (pos=n ; pos >= 0; pos--) { if (huffNode[pos].nbBits >= currentNbBits) continue; currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ - rankLast[maxNbBits-currentNbBits] = pos; + rankLast[maxNbBits-currentNbBits] = (U32)pos; } } while (totalCost > 0) { - U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; + U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { - U32 highPos = rankLast[nBitsToDecrease]; - U32 lowPos = rankLast[nBitsToDecrease-1]; + U32 const highPos = rankLast[nBitsToDecrease]; + U32 const lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; if (lowPos == noSymbol) break; { U32 const highTotal = huffNode[highPos].count; @@ -277,7 +277,8 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; - rankLast[1] = n+1; + assert(n >= 0); + rankLast[1] = (U32)(n+1); totalCost++; continue; } @@ -339,10 +340,10 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; nodeElt* const huffNode = huffNode0+1; - U32 n, nonNullRank; + int nonNullRank; int lowS, lowN; - U16 nodeNb = STARTNODE; - U32 nodeRoot; + int nodeNb = STARTNODE; + int n, nodeRoot; /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ @@ -357,21 +358,21 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); /* init for parents */ - nonNullRank = maxSymbolValue; + nonNullRank = (int)maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; - huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; + huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb; nodeNb++; lowS-=2; for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ /* create parents */ while (nodeNb <= nodeRoot) { - U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; - huffNode[n1].parent = huffNode[n2].parent = nodeNb; + huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb; nodeNb++; } @@ -383,24 +384,25 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; /* enforce maxTableLog */ - maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); + maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); /* fill result into tree (val, nbBits) */ { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ for (n=0; n<=nonNullRank; n++) nbPerRank[huffNode[n].nbBits]++; /* determine stating value per rank */ { U16 min = 0; - for (n=maxNbBits; n>0; n--) { + for (n=(int)maxNbBits; n>0; n--) { valPerRank[n] = min; /* get starting value within each rank */ min += nbPerRank[n]; min >>= 1; } } - for (n=0; n<=maxSymbolValue; n++) + for (n=0; n Date: Mon, 4 May 2020 18:59:26 -0400 Subject: [PATCH 326/402] Mark zstddeclib-in.c Not Executable --- contrib/single_file_libs/zstddeclib-in.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 contrib/single_file_libs/zstddeclib-in.c diff --git a/contrib/single_file_libs/zstddeclib-in.c b/contrib/single_file_libs/zstddeclib-in.c old mode 100755 new mode 100644 From 6381b7ee3f6a4cbee65d490fae464915e722aebd Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 4 May 2020 18:59:47 -0400 Subject: [PATCH 327/402] Add Fallback When realpath Doesn't Support --relative-to --- contrib/single_file_libs/combine.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index a98eef28396..40f42025613 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -72,7 +72,11 @@ resolve_include() { local inc=$2 for root in $srcdir $ROOTS; do if [ -f "$root/$inc" ]; then - echo "$(realpath --relative-to . "$root/$inc")" + local relpath="$(realpath --relative-to . "$root/$inc")" + if [ "$?" -eq "0" ]; then # not all realpaths support --relative-to + relpath="$(realpath "$root/$inc")" + fi + echo "$relpath" return 0 fi done From 7120d97cb3d3ad65986fb653f0fdec7fd7a346b8 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 5 May 2020 09:08:05 -0700 Subject: [PATCH 328/402] fix minor conversion warnings (#2106) --- lib/compress/huf_compress.c | 48 +++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index 533f7cb25d0..a6c871a5e69 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -88,18 +88,18 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); /* Write table description header */ - { CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); + { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); op += hSize; } /* Compress */ CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) ); + { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) ); if (cSize == 0) return 0; /* not enough space for compressed data */ op += cSize; } - return op-ostart; + return (size_t)(op-ostart); } @@ -220,7 +220,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* there are several too large elements (at least >= 2) */ { int totalCost = 0; const U32 baseCost = 1 << (largestBits - maxNbBits); - U32 n = lastNonNull; + int n = (int)lastNonNull; while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); @@ -235,22 +235,22 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) /* repay normalized cost */ { U32 const noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_TABLELOG_MAX+2]; - int pos; /* Get pos of last (smallest) symbol per rank */ memset(rankLast, 0xF0, sizeof(rankLast)); { U32 currentNbBits = maxNbBits; + int pos; for (pos=n ; pos >= 0; pos--) { if (huffNode[pos].nbBits >= currentNbBits) continue; currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ - rankLast[maxNbBits-currentNbBits] = pos; + rankLast[maxNbBits-currentNbBits] = (U32)pos; } } while (totalCost > 0) { - U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; + U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { - U32 highPos = rankLast[nBitsToDecrease]; - U32 lowPos = rankLast[nBitsToDecrease-1]; + U32 const highPos = rankLast[nBitsToDecrease]; + U32 const lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; if (lowPos == noSymbol) break; { U32 const highTotal = huffNode[highPos].count; @@ -277,7 +277,8 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; - rankLast[1] = n+1; + assert(n >= 0); + rankLast[1] = (U32)(n+1); totalCost++; continue; } @@ -339,10 +340,10 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; nodeElt* const huffNode = huffNode0+1; - U32 n, nonNullRank; + int nonNullRank; int lowS, lowN; - U16 nodeNb = STARTNODE; - U32 nodeRoot; + int nodeNb = STARTNODE; + int n, nodeRoot; /* safety checks */ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ @@ -357,21 +358,21 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); /* init for parents */ - nonNullRank = maxSymbolValue; + nonNullRank = (int)maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; - huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; + huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb; nodeNb++; lowS-=2; for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ /* create parents */ while (nodeNb <= nodeRoot) { - U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; - huffNode[n1].parent = huffNode[n2].parent = nodeNb; + huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb; nodeNb++; } @@ -383,24 +384,25 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; /* enforce maxTableLog */ - maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); + maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); /* fill result into tree (val, nbBits) */ { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ for (n=0; n<=nonNullRank; n++) nbPerRank[huffNode[n].nbBits]++; /* determine stating value per rank */ { U16 min = 0; - for (n=maxNbBits; n>0; n--) { + for (n=(int)maxNbBits; n>0; n--) { valPerRank[n] = min; /* get starting value within each rank */ min += nbPerRank[n]; min >>= 1; } } - for (n=0; n<=maxSymbolValue; n++) + for (n=0; n Date: Tue, 5 May 2020 09:51:44 -0700 Subject: [PATCH 329/402] fixing inconsistencies --- programs/zstdgrep | 209 ++++++++++++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 82 deletions(-) diff --git a/programs/zstdgrep b/programs/zstdgrep index 61efaa9474a..168ec281eb8 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -28,8 +28,6 @@ zcat=${ZCAT:-zstdcat} endofopts=0 pattern_found=0 grep_args="" -hyphen=0 -silent=0 prog=${0##*/} @@ -43,92 +41,139 @@ esac # skip all options and pass them on to grep taking care of options # with arguments, and if -e was supplied +escape=' + s/'\''/'\''\\'\'''\''/g + $s/$/'\''/ +' + +operands= +files_with_matches=0 +files_without_matches=0 +no_filename=0 +with_filename=0 + while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do - case "$1" in - # from GNU grep-2.5.1 -- keep in sync! - -[ABCDXdefm]) - if [ "$#" -lt 2 ]; then - printf '%s: missing argument for %s flag\n' "${prog}" "$1" >&2 - exit 1 - fi - case "$1" in - -e) - pattern="$2" - pattern_found=1 - shift 2 - break - ;; - -f) - pattern_found=2 - ;; - *) - ;; + option=$1 + shift + optarg= + + case $option in + (-[0123456789EFGHIKLPRTUVZabchilnoqrsuvwxyz]?*) + arg2=-\'$(expr "X$option" : 'X-.[0-9]*\(.*\)' | sed "$escape") + eval "set -- $arg2 "'${1+"$@"}' + option=$(expr "X$option" : 'X\(-.[0-9]*\)');; + (--binary-*=* | --[lm]a*=* | --reg*=*) ;; + (-[ABCDXdefm] | binary-* | --file | --[lm]a* | --reg*) + case ${1?"$option option requires an argument"} in + (*\'*) optarg=" '"$(printf '%s\n' "$1" | sed "$escape");; + (*) optarg=" '$1'";; esac - grep_args="${grep_args} $1 $2" - shift 2 - ;; - --) - shift - endofopts=1 - ;; - -) - hyphen=1 - shift - ;; - -h) - silent=1 - shift - ;; - -*) - grep_args="${grep_args} $1" - shift - ;; - *) - # pattern to grep for + shift;; + (-f?*\'*) optarg=" '"$(expr "X$option" : 'X-f\(.*\)' | sed "$escape"); option=-f;; + (-f?*) optarg=" '"$(expr "X$option" : 'X-f\(.*\)')\'; option=-f;; + (--file=*\'*) optarg=" '"$(expr "X$option" : 'X--file=\(.*\)' | sed "$escape"); option=--file;; + (--file=*) optarg=" '"$(expr "X$option" : 'X--file=\(.*\)')\'; option=--file;; + (--) endofopts=1; break;; + (-?*) ;; + (*) + case $option in + (*\'*) operands="$operands '"$(printf '%s\n' "$option" | sed "$escape");; + (*) operands="$operands '$option'";; + esac + ${POSIXLY_CORRECT+break} endofopts=1 - ;; + continue;; + esac + + case $option in + (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*) + printf >&2 '%s: %s: option not supported\n' "$0" "$option" + exit 2;; + (-e* | --reg*) pattern_found=1;; + (-f | --file) + case $optarg in + (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'") + option=-e + optarg=" '"$(sed "$escape") || exit 2;; + esac + pattern_found=1;; + (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \ + | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \ + | --with-filename) + with_filename=1 + continue;; + (-l | --files-with-*) files_with_matches=1;; + (-L | --files-witho*) files_without_matches=1;; + (-h | --no-f*) no_filename=1;; + esac + + case $option in + (*\'?*) option=\'$(printf '%s\n' "$option" | sed "$escape");; + (*) option="'$option'";; + esac + + grep_args="$option$optarg" + grep="$grep $grep_args" + done + +eval "set -- $operands "'${1+"$@"}' + +if test $pattern_found -eq 0; then + case ${1?"missing pattern; try \`$0 --help' for help"} in + (*\'*) grep="$grep -- '"$(printf '%s\n' "$1" | sed "$escape");; + (*) grep="$grep -- '$1'";; esac -done + shift +fi -# if no -e option was found, take next argument as grep-pattern -if [ "${pattern_found}" -lt 1 ]; then - if [ "$#" -ge 1 ]; then - pattern="$1" - shift - elif [ "${hyphen}" -gt 0 ]; then - pattern="-" - else - printf '%s: missing pattern\n' "${prog}" >&2 - exit 1 - fi +if test $# -eq 0; then + set -- - fi -EXIT_CODE=0 -# call grep ... -if [ "$#" -lt 1 ]; then - # ... on stdin - set -f # Disable file name generation (globbing). - # shellcheck disable=SC2086 - "${zcat}" - | "${grep}" ${grep_args} -- "${pattern}" - - EXIT_CODE=$? - set +f -else - # ... on all files given on the command line - if [ "${silent}" -lt 1 ] && [ "$#" -gt 1 ]; then - grep_args="-H ${grep_args}" - fi - set -f - while [ "$#" -gt 0 ]; do - # shellcheck disable=SC2086 - if [ $pattern_found -eq 2 ]; then - "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - +exec 3>&1 +res=0 + +for i do + zcat_status=$( + exec 5>&1 + ($zcat -- "$i" 5>&-; echo $? >&5) 3>&- | + if test $files_with_matches -eq 1; then + eval "$grep" >/dev/null && { printf '%s\n' "$i" || exit 2; } + elif test $files_without_matches -eq 1; then + eval "$grep" >/dev/null || { + r=$? + if test $r -eq 1; then + printf '%s\n' "$i" || r=2 + fi + exit $r + } + elif test $with_filename -eq 0 && { test $# -eq 1 || test $no_filename -eq 1; }; then + eval "$grep" else - "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - - fi - [ "$?" -ne 0 ] && EXIT_CODE=1 - shift - done - set +f -fi + case $i in + (*' + '* | *'&'* | *'\'* | *'|'*) + i=$(printf '%s\n' "$i" | + sed ' + $!N + $s/[&\|]/\\&/g + $s/\n/\\n/g + ');; + esac + sed_script="s|^|$i:|" -exit "${EXIT_CODE}" + # Fail if grep or sed fails. + r=$( + exec 4>&1 + (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&- + ) && exit $r + r=$? + test 1 -lt $r && exit $r || exit 2 + fi >&3 5>&- + ) + r=$? + test 128 -lt $r && exit $r + test "$zcat_status" -eq 0 || test "$zcat_status" -eq 2 || r=2 + test $res -lt $r && res=$r +done +exit $res From 6ff16b42462ea41402d10b0fec0ba78934002db4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 5 May 2020 10:03:57 -0700 Subject: [PATCH 330/402] adding help text --- programs/zstdgrep | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/programs/zstdgrep b/programs/zstdgrep index 168ec281eb8..60d5fe16d1e 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -46,6 +46,24 @@ escape=' $s/$/'\''/ ' +# We might want to create a c program in the future +# and replace this file with that if these +# unsupported options become necessary +usage="Usage: $0 [OPTION]... [-e] PATTERN [FILE]... +OPTIONs are the same as grep with the exception of +the following unsupported options: + --dereference-recursive (-R) + --directories (-d) + --exclude + --exclude-from + --exclude-dir + --include + --null (-Z), + --null-data (-z) + --recursive (-r) +grep --help below: +" + operands= files_with_matches=0 files_without_matches=0 @@ -97,6 +115,7 @@ while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do optarg=" '"$(sed "$escape") || exit 2;; esac pattern_found=1;; + (--h | --he | --hel | --help) echo "$usage"; eval "$grep --help" || exit 2; exit;; (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \ | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \ | --with-filename) From c29fd7cd8be73bdb6822966eb968c89861598d03 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 5 May 2020 10:16:59 -0700 Subject: [PATCH 331/402] some more conversion warnings hunting down some static analyzer warnings --- lib/compress/huf_compress.c | 22 ++++++++++++++-------- lib/compress/zstd_compress_sequences.c | 8 ++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/compress/huf_compress.c b/lib/compress/huf_compress.c index a6c871a5e69..4efffbb542a 100644 --- a/lib/compress/huf_compress.c +++ b/lib/compress/huf_compress.c @@ -565,7 +565,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, if (srcSize < 12) return 0; /* no saving possible : too small input */ op += 6; /* jumpTable */ - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart, (U16)cSize); @@ -573,7 +574,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart+2, (U16)cSize); @@ -581,7 +583,8 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) ); + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); if (cSize==0) return 0; assert(cSize <= 65535); MEM_writeLE16(ostart+4, (U16)cSize); @@ -589,12 +592,14 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, } ip += segmentSize; - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, iend-ip, CTable, bmi2) ); + assert(op <= oend); + assert(ip <= iend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) ); if (cSize==0) return 0; op += cSize; } - return op-ostart; + return (size_t)(op-ostart); } size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) @@ -610,14 +615,15 @@ static size_t HUF_compressCTable_internal( HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2) { size_t const cSize = (nbStreams==HUF_singleStream) ? - HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) : - HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2); + HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) : + HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2); if (HUF_isError(cSize)) { return cSize; } if (cSize==0) { return 0; } /* uncompressible */ op += cSize; /* check compressibility */ + assert(op >= ostart); if ((size_t)(op-ostart) >= srcSize-1) { return 0; } - return op-ostart; + return (size_t)(op-ostart); } typedef struct { diff --git a/lib/compress/zstd_compress_sequences.c b/lib/compress/zstd_compress_sequences.c index 23a5f3532c9..f9f8097c839 100644 --- a/lib/compress/zstd_compress_sequences.c +++ b/lib/compress/zstd_compress_sequences.c @@ -111,7 +111,7 @@ size_t ZSTD_fseBitCost( DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s); return ERROR(GENERIC); } - cost += count[s] * bitCost; + cost += (size_t)count[s] * bitCost; } return cost >> kAccuracyLog; } @@ -129,7 +129,7 @@ size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog, unsigned s; assert(accuracyLog <= 8); for (s = 0; s <= max; ++s) { - unsigned const normAcc = norm[s] != -1 ? norm[s] : 1; + unsigned const normAcc = (norm[s] != -1) ? (unsigned)norm[s] : 1; unsigned const norm256 = normAcc << shift; assert(norm256 > 0); assert(norm256 < 256); @@ -294,7 +294,7 @@ ZSTD_encodeSequences_body( if (MEM_32bits()) BIT_flushBits(&blockStream); if (longOffsets) { U32 const ofBits = ofCodeTable[nbSeq-1]; - int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); + unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); if (extraBits) { BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits); BIT_flushBits(&blockStream); @@ -331,7 +331,7 @@ ZSTD_encodeSequences_body( BIT_addBits(&blockStream, sequences[n].matchLength, mlBits); if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream); if (longOffsets) { - int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); + unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); if (extraBits) { BIT_addBits(&blockStream, sequences[n].offset, extraBits); BIT_flushBits(&blockStream); /* (7)*/ From 229cbd056e42375096bb6a2f5e2fc5fc73fd097b Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 5 May 2020 13:18:45 -0400 Subject: [PATCH 332/402] Fix Fallbacks to Work on FreeBSD --- contrib/single_file_libs/combine.sh | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index 40f42025613..a129722646a 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -72,11 +72,28 @@ resolve_include() { local inc=$2 for root in $srcdir $ROOTS; do if [ -f "$root/$inc" ]; then + # Try to reduce the file path into a canonical form (so that multiple) + # includes of the same file are successfully deduplicated, even if they + # are expressed differently. local relpath="$(realpath --relative-to . "$root/$inc")" - if [ "$?" -eq "0" ]; then # not all realpaths support --relative-to - relpath="$(realpath "$root/$inc")" + if [ "$relpath" != "" ]; then # not all realpaths support --relative-to + echo "$relpath" + return 0 fi - echo "$relpath" + local relpath="$(realpath "$root/$inc")" + if [ "$relpath" != "" ]; then # not all distros have realpath... + echo "$relpath" + return 0 + fi + # Worst case, fall back to just the root + relative include path. The + # problem with this is that it is possible to emit multiple different + # resolved paths to the same file, depending on exactly how its included. + # Since the main loop below keeps a list of the resolved paths it's + # already included, in order to avoid repeated includes, this failure to + # produce a canonical/reduced path can lead to multiple inclusions of the + # same file. But it seems like the resulting single file library still + # works (hurray include guards!), so I guess it's ok. + echo "$root/$inc" return 0 fi done @@ -91,7 +108,7 @@ add_file() { # Log but only if not writing to stdout echo "Processing: $file" fi - # Get directory to resolve relative includes + # Get directory of the current so we can resolve relative includes local srcdir="$(dirname "$file")" # Read the file local line= From bdfb50f7c4413f3edbe9c70191088a724a322e4e Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 5 May 2020 13:58:22 -0400 Subject: [PATCH 333/402] Uhhh It's Still Failing, Let's Try Printing Debug Info? --- contrib/single_file_libs/combine.sh | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index a129722646a..7c12fcdeb9c 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -41,11 +41,15 @@ usage() { } # Tests that the grep implementation works as expected (older OSX grep fails) -test_grep() { +test_deps() { if ! echo '#include "foo"' | grep -Eq '^\s*#\s*include\s*".+"'; then echo "Aborting: the grep implementation fails to parse include lines" exit 1 fi + if ! echo '"foo.h"' | sed 's/"\([^"]\+\)"/\1/' | grep -Eq '^foo\.h$'; then + echo "Aborting: sed is unavailable or non-functional" + exit 1 + fi } # Tests if list $1 has item $2 (returning zero on a match) @@ -66,6 +70,10 @@ write_line() { fi } +log_line() { + echo $@ >&2 +} + # Find this file! resolve_include() { local srcdir=$1 @@ -104,10 +112,7 @@ resolve_include() { add_file() { local file=$1 if [ -n "$file" ]; then - if [ -n "$DESTN" ]; then - # Log but only if not writing to stdout - echo "Processing: $file" - fi + log_line "Processing: $file" # Get directory of the current so we can resolve relative includes local srcdir="$(dirname "$file")" # Read the file @@ -120,6 +125,7 @@ add_file() { if list_has_item "$XINCS" "$inc"; then # The file was excluded so error if the source attempts to use it write_line "#error Using excluded file: $inc" + log_line "Excluding: $res_inc ($inc)" else if ! list_has_item "$FOUND" "$res_inc"; then # The file was not previously encountered @@ -128,6 +134,7 @@ add_file() { # But the include was flagged to keep as included write_line "/**** *NOT* inlining $inc ****/" write_line "$line" + log_line "Not Inlining: $res_inc ($inc)" else # The file was neither excluded nor seen before so inline it write_line "/**** start inlining $inc ****/" @@ -136,6 +143,7 @@ add_file() { fi else write_line "/**** skipping file: $inc ****/" + log_line "Skipping: $res_inc ($inc)" fi fi else @@ -153,10 +161,7 @@ add_file() { done < "$file" else write_line "#error Unable to find \"$1\"" - if [ -n "$DESTN" ]; then - # Log but only if not writing to stdout - echo "Error: Unable to find: \"$1\"" - fi + log_line "Error: Unable to find: \"$1\"" fi } @@ -189,7 +194,7 @@ if [ -n "$1" ]; then if [ -n "$DESTN" ]; then printf "" > "$DESTN" fi - test_grep + test_deps add_file "$1" else echo "Input file not found: \"$1\"" From 005ffd3bdb14edc2cf21d8902266f21494127968 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 5 May 2020 14:54:04 -0400 Subject: [PATCH 334/402] Fix Sed Regex Escaping for Extended Regex Rules...... --- contrib/single_file_libs/combine.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index 7c12fcdeb9c..2fef0541cbf 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -46,7 +46,7 @@ test_deps() { echo "Aborting: the grep implementation fails to parse include lines" exit 1 fi - if ! echo '"foo.h"' | sed 's/"\([^"]\+\)"/\1/' | grep -Eq '^foo\.h$'; then + if ! echo '"foo.h"' | sed -E 's/"([^"]+)"/\1/' | grep -Eq '^foo\.h$'; then echo "Aborting: sed is unavailable or non-functional" exit 1 fi @@ -120,7 +120,7 @@ add_file() { while IFS= read -r line; do if echo "$line" | grep -Eq '^\s*#\s*include\s*".+"'; then # We have an include directive so strip the (first) file - local inc=$(echo "$line" | grep -Eo '".*"' | sed 's/"\([^"]\+\)"/\1/' | head -1) + local inc=$(echo "$line" | grep -Eo '".*"' | sed -E 's/"([^"]+)"/\1/' | head -1) local res_inc="$(resolve_include "$srcdir" "$inc")" if list_has_item "$XINCS" "$inc"; then # The file was excluded so error if the source attempts to use it From 5163778c02387cda6cb3f191ea08ac5b5e39c37c Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Tue, 5 May 2020 15:25:18 -0400 Subject: [PATCH 335/402] Yay It Works, Clean Up Logging A Bit --- contrib/single_file_libs/combine.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh index 2fef0541cbf..05c7bce8e5c 100755 --- a/contrib/single_file_libs/combine.sh +++ b/contrib/single_file_libs/combine.sh @@ -83,12 +83,12 @@ resolve_include() { # Try to reduce the file path into a canonical form (so that multiple) # includes of the same file are successfully deduplicated, even if they # are expressed differently. - local relpath="$(realpath --relative-to . "$root/$inc")" + local relpath="$(realpath --relative-to . "$root/$inc" 2>/dev/null)" if [ "$relpath" != "" ]; then # not all realpaths support --relative-to echo "$relpath" return 0 fi - local relpath="$(realpath "$root/$inc")" + local relpath="$(realpath "$root/$inc" 2>/dev/null)" if [ "$relpath" != "" ]; then # not all distros have realpath... echo "$relpath" return 0 @@ -125,7 +125,7 @@ add_file() { if list_has_item "$XINCS" "$inc"; then # The file was excluded so error if the source attempts to use it write_line "#error Using excluded file: $inc" - log_line "Excluding: $res_inc ($inc)" + log_line "Excluding: $inc" else if ! list_has_item "$FOUND" "$res_inc"; then # The file was not previously encountered @@ -134,7 +134,7 @@ add_file() { # But the include was flagged to keep as included write_line "/**** *NOT* inlining $inc ****/" write_line "$line" - log_line "Not Inlining: $res_inc ($inc)" + log_line "Not Inlining: $inc" else # The file was neither excluded nor seen before so inline it write_line "/**** start inlining $inc ****/" @@ -143,7 +143,6 @@ add_file() { fi else write_line "/**** skipping file: $inc ****/" - log_line "Skipping: $res_inc ($inc)" fi fi else From 4f755bdafc92befeb003a2e55ba50b7a68301600 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Tue, 5 May 2020 14:08:35 -0700 Subject: [PATCH 336/402] faster cygwin test The cygwin test on Appveyor is way too long (>30 mn). The main issue is the very long zstreamtest, because no time out has been programmed. Ensures that both fuzzer and zstreamtest receive a 30sec slot. Should reduce cygwin tests duration by -30mn. --- appveyor.yml | 2 +- build/cmake/tests/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index aae626d00f0..fdc87376c8c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -249,7 +249,7 @@ C:\cygwin64\bin\bash --login -c " set -e; cd build/cmake; - CFLAGS='-Werror' cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_FUZZER_FLAGS=-T30s .; + CFLAGS='-Werror' cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug -DZSTD_BUILD_TESTS:BOOL=ON -DZSTD_FUZZER_FLAGS=-T30s -DZSTD_ZSTREAM_FLAGS=-T30s .; make -j4; ctest -V -L Medium; " diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt index 78cf3270773..95d60f5f3ef 100644 --- a/build/cmake/tests/CMakeLists.txt +++ b/build/cmake/tests/CMakeLists.txt @@ -70,7 +70,7 @@ AddTestFlagsOption(ZSTD_FUZZER_FLAGS "$ENV{FUZZERTEST} $ENV{FUZZER_FLAGS}" add_test(NAME fuzzer COMMAND fuzzer ${ZSTD_FUZZER_FLAGS}) # Disable the timeout since the run time is too long for the default timeout of # 1500 seconds and varies considerably between low-end and high-end CPUs. -set_tests_properties(fuzzer PROPERTIES TIMEOUT 0) +# set_tests_properties(fuzzer PROPERTIES TIMEOUT 0) # # zstreamtest From 250184adf6639eedc5e9114689aafe0987b3ffb2 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 5 May 2020 16:51:06 -0700 Subject: [PATCH 337/402] adding tests back --- tests/playTests.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/playTests.sh b/tests/playTests.sh index 3c91b958f18..90575c0cc77 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -254,6 +254,38 @@ ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst && die "Should have failed ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst | grep "No such file or directory" || true rm -f tmp_grep* +println "\n===> zstdgrep pipe in with -f " +echo "start" > tmp_grep +echo "stop" >> tmp_grep +echo "start" | ZCAT=./zstdcat $ZSTDGREP -f - tmp_grep > tmp_grep_out1 +echo "start" | grep -f - tmp_grep > tmp_grep_out2 +$DIFF tmp_grep_out1 tmp_grep_out2 +rm -f tmp_grep* + +println "\n===> zstdgrep --regexp= multiple" +echo "start" > tmp_grep +echo "stop" >> tmp_grep +ZCAT=./zstdcat $ZSTDGREP --regexp=start --regexp=stop tmp_grep > tmp_grep_out1 +grep -e start -e stop tmp_grep > tmp_grep_out2 +$DIFF tmp_grep_out1 tmp_grep_out2 +rm -f tmp_grep* + +println "\n===> zstdgrep multiple -e" +echo "start" > tmp_grep +echo "stop" >> tmp_grep +ZCAT=./zstdcat $ZSTDGREP -e start -e stop tmp_grep > tmp_grep_out1 +grep -e start -e stop tmp_grep > tmp_grep_out2 +$DIFF tmp_grep_out1 tmp_grep_out2 +rm -f tmp_grep* + +println "\n===> zstdgrep multiple --regexp" +echo "start" > tmp_grep +echo "stop" >> tmp_grep +ZCAT=./zstdcat $ZSTDGREP --regexp start --regexp stop tmp_grep > tmp_grep_out1 +grep -e start -e stop tmp_grep > tmp_grep_out2 +$DIFF tmp_grep_out1 tmp_grep_out2 +rm -f tmp_grep* + println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir From 5717bd39ee1bd5d2855023652336deeb722a57d5 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 1 May 2020 16:35:35 -0700 Subject: [PATCH 338/402] [lib] Fix NULL pointer dereference When the output buffer is `NULL` with size 0, but the frame content size is non-zero, we will write to the NULL pointer because our bounds check underflowed. This was exposed by a recent PR that allowed an empty frame into the single-pass shortcut in streaming mode. * Fix the bug. * Fix another NULL dereference in zstd-v1. * Overflow checks in 32-bit mode. * Add a dedicated test. * Expose the bug in the dedicated simple_decompress fuzzer. * Switch all mallocs in fuzzers to return NULL for size=0. * Fix a new timeout in a fuzzer. Neither clang nor gcc show a decompression speed regression on x86-64. On x86-32 clang is slightly positive and gcc loses 2.5% of speed. Credit to OSS-Fuzz. --- lib/common/xxhash.c | 4 ++- lib/decompress/zstd_decompress_block.c | 46 ++++++++++++++++++-------- lib/legacy/zstd_v01.c | 16 ++++++--- lib/legacy/zstd_v02.c | 10 ++++-- lib/legacy/zstd_v03.c | 10 ++++-- lib/legacy/zstd_v04.c | 10 ++++-- lib/legacy/zstd_v05.c | 6 ++-- lib/legacy/zstd_v06.c | 6 ++-- lib/legacy/zstd_v07.c | 14 +++++--- tests/fuzz/Makefile | 2 +- tests/fuzz/block_decompress.c | 3 +- tests/fuzz/block_round_trip.c | 11 +++--- tests/fuzz/dictionary_decompress.c | 3 +- tests/fuzz/dictionary_loader.c | 8 ++--- tests/fuzz/dictionary_round_trip.c | 6 ++-- tests/fuzz/fuzz_data_producer.c | 4 +-- tests/fuzz/fuzz_helpers.c | 32 ++++++++++++++++++ tests/fuzz/fuzz_helpers.h | 11 ++++++ tests/fuzz/simple_compress.c | 3 +- tests/fuzz/simple_decompress.c | 3 +- tests/fuzz/simple_round_trip.c | 8 ++--- tests/fuzz/stream_decompress.c | 7 ++-- tests/fuzz/stream_round_trip.c | 7 ++-- tests/fuzz/zstd_frame_info.c | 3 ++ tests/fuzz/zstd_helpers.c | 8 ++--- tests/fuzzer.c | 6 ++++ 26 files changed, 167 insertions(+), 80 deletions(-) create mode 100644 tests/fuzz/fuzz_helpers.c diff --git a/lib/common/xxhash.c b/lib/common/xxhash.c index 72314c59f36..597de18fc89 100644 --- a/lib/common/xxhash.c +++ b/lib/common/xxhash.c @@ -709,7 +709,9 @@ FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, c state->total_len += len; if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + if (input != NULL) { + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + } state->memsize += (U32)len; return XXH_OK; } diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 6eb7462cd10..3b9ba37717b 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -665,15 +665,15 @@ size_t ZSTD_execSequenceEnd(BYTE* op, { BYTE* const oLitEnd = op + sequence.litLength; size_t const sequenceLength = sequence.litLength + sequence.matchLength; - BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ const BYTE* const iLitEnd = *litPtr + sequence.litLength; const BYTE* match = oLitEnd - sequence.offset; BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; - /* bounds checks */ - assert(oLitEnd < oMatchEnd); - RETURN_ERROR_IF(oMatchEnd > oend, dstSize_tooSmall, "last match must fit within dstBuffer"); - RETURN_ERROR_IF(iLitEnd > litLimit, corruption_detected, "try to read beyond literal buffer"); + /* bounds checks : careful of address space overflow in 32-bit mode */ + RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer"); + RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer"); + assert(op < op + sequenceLength); + assert(oLitEnd < op + sequenceLength); /* copy literals */ ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap); @@ -709,16 +709,27 @@ size_t ZSTD_execSequence(BYTE* op, BYTE* const oLitEnd = op + sequence.litLength; size_t const sequenceLength = sequence.litLength + sequence.matchLength; BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; /* risk : address space underflow on oend=NULL */ const BYTE* const iLitEnd = *litPtr + sequence.litLength; const BYTE* match = oLitEnd - sequence.offset; - /* Errors and uncommon cases handled here. */ - assert(oLitEnd < oMatchEnd); - if (UNLIKELY(iLitEnd > litLimit || oMatchEnd > oend_w)) + assert(op != NULL /* Precondition */); + assert(oend_w < oend /* No underflow */); + /* Handle edge cases in a slow path: + * - Read beyond end of literals + * - Match end is within WILDCOPY_OVERLIMIT of oend + * - 32-bit mode and the match length overflows + */ + if (UNLIKELY( + iLitEnd > litLimit || + oMatchEnd > oend_w || + (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH))) return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */ + assert(op <= oLitEnd /* No overflow */); + assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */); + assert(oMatchEnd <= oend /* No underflow */); assert(iLitEnd <= litLimit /* Literal length is in bounds */); assert(oLitEnd <= oend_w /* Can wildcopy literals */); assert(oMatchEnd <= oend_w /* Can wildcopy matches */); @@ -968,6 +979,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + assert(dst != NULL); ZSTD_STATIC_ASSERT( BIT_DStream_unfinished < BIT_DStream_completed && @@ -1043,8 +1055,10 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, /* last literal segment */ { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (op != NULL) { + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } return op-ostart; @@ -1093,6 +1107,7 @@ ZSTD_decompressSequencesLong_body( seqState.prefixStart = prefixStart; seqState.pos = (size_t)(op-prefixStart); seqState.dictEnd = dictEnd; + assert(dst != NULL); assert(iend >= ip); RETURN_ERROR_IF( ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), @@ -1134,8 +1149,10 @@ ZSTD_decompressSequencesLong_body( /* last literal segment */ { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (op != NULL) { + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } return op-ostart; @@ -1255,7 +1272,6 @@ ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable) } #endif - size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, @@ -1297,6 +1313,8 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, ip += seqHSize; srcSize -= seqHSize; + RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled"); + #if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) if ( !usePrefetchDecoder diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index 0517222ca5c..eb23628330e 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -1078,7 +1078,7 @@ static size_t HUF_decompress_usingDTable( /* -3% slower when non static */ BYTE* const ostart = (BYTE*) dst; BYTE* op = ostart; BYTE* const omax = op + maxDstSize; - BYTE* const olimit = omax-15; + BYTE* const olimit = maxDstSize < 15 ? op : omax-15; const void* ptr = DTable; const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1; @@ -1483,7 +1483,9 @@ static size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProper static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } return srcSize; } @@ -1541,7 +1543,9 @@ static size_t ZSTDv01_decodeLiteralsBlock(void* ctx, size_t rleSize = litbp.origSize; if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall); if (!srcSize) return ERROR(srcSize_wrong); - memset(oend - rleSize, *ip, rleSize); + if (rleSize > 0) { + memset(oend - rleSize, *ip, rleSize); + } *litStart = oend - rleSize; *litSize = rleSize; ip++; @@ -1901,8 +1905,10 @@ static size_t ZSTD_decompressSequences( { size_t lastLLSize = litEnd - litPtr; if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - if (op != litPtr) memmove(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + if (op != litPtr) memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } } } diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index a7aa27cdfe2..32d45a6d4bd 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -2836,7 +2836,9 @@ static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockPropertie static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } return srcSize; } @@ -3229,8 +3231,10 @@ static size_t ZSTD_decompressSequences( size_t lastLLSize = litEnd - litPtr; if (litPtr > litEnd) return ERROR(corruption_detected); if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - if (op != litPtr) memmove(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + if (op != litPtr) memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } } } diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 1b00c98bfea..b541eae2abb 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -2477,7 +2477,9 @@ static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockPropertie static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } return srcSize; } @@ -2870,8 +2872,10 @@ static size_t ZSTD_decompressSequences( size_t lastLLSize = litEnd - litPtr; if (litPtr > litEnd) return ERROR(corruption_detected); if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - if (op != litPtr) memmove(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + if (op != litPtr) memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } } } diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index 1a3d49cf694..56bf4522249 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -2603,7 +2603,9 @@ static size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockPropertie static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) { if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } return srcSize; } @@ -3008,8 +3010,10 @@ static size_t ZSTD_decompressSequences( size_t lastLLSize = litEnd - litPtr; if (litPtr > litEnd) return ERROR(corruption_detected); if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - if (op != litPtr) memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + if (op != litPtr) memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } } diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 79ea59a1b84..243d222562e 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -3362,8 +3362,10 @@ static size_t ZSTDv05_decompressSequences( size_t lastLLSize = litEnd - litPtr; if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */ if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } return op-ostart; diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 1a670fad0fb..c56f582772f 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -3501,8 +3501,10 @@ static size_t ZSTDv06_decompressSequences( { size_t const lastLLSize = litEnd - litPtr; if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */ if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } return op-ostart; diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index 5393475dad0..9f3a597f125 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -3272,7 +3272,9 @@ static size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProper static size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } return srcSize; } @@ -3714,8 +3716,10 @@ static size_t ZSTDv07_decompressSequences( { size_t const lastLLSize = litEnd - litPtr; /* if (litPtr > litEnd) return ERROR(corruption_detected); */ /* too many literals already used */ if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; + if (lastLLSize > 0) { + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } return op-ostart; @@ -3776,7 +3780,9 @@ ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockS static size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length) { if (length > dstCapacity) return ERROR(dstSize_tooSmall); - memset(dst, byte, length); + if (length > 0) { + memset(dst, byte, length); + } return length; } diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index a7f3a73a068..571ab553bd7 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -42,7 +42,7 @@ FUZZ_ARFLAGS := $(ARFLAGS) FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS) FUZZ_HEADERS := fuzz_helpers.h fuzz.h zstd_helpers.h fuzz_data_producer.h -FUZZ_SRC := $(PRGDIR)/util.c zstd_helpers.c fuzz_data_producer.c +FUZZ_SRC := $(PRGDIR)/util.c fuzz_helpers.c zstd_helpers.c fuzz_data_producer.c ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c diff --git a/tests/fuzz/block_decompress.c b/tests/fuzz/block_decompress.c index f2a280b6ca9..64d70f005e9 100644 --- a/tests/fuzz/block_decompress.c +++ b/tests/fuzz/block_decompress.c @@ -32,9 +32,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) /* Allocate all buffers and contexts if not already allocated */ if (neededBufSize > bufSize) { free(rBuf); - rBuf = malloc(neededBufSize); + rBuf = FUZZ_malloc(neededBufSize); bufSize = neededBufSize; - FUZZ_ASSERT(rBuf); } if (!dctx) { dctx = ZSTD_createDCtx(); diff --git a/tests/fuzz/block_round_trip.c b/tests/fuzz/block_round_trip.c index 8048cb263c3..097fc01b89b 100644 --- a/tests/fuzz/block_round_trip.c +++ b/tests/fuzz/block_round_trip.c @@ -43,7 +43,9 @@ static size_t roundTripTest(void *result, size_t resultCapacity, FUZZ_ZASSERT(ret); if (ret == 0) { FUZZ_ASSERT(resultCapacity >= srcSize); - memcpy(result, src, srcSize); + if (srcSize > 0) { + memcpy(result, src, srcSize); + } return srcSize; } ZSTD_decompressBegin(dctx); @@ -67,10 +69,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) if (neededBufSize > bufSize || !cBuf || !rBuf) { free(cBuf); free(rBuf); - cBuf = malloc(neededBufSize); - rBuf = malloc(neededBufSize); + cBuf = FUZZ_malloc(neededBufSize); + rBuf = FUZZ_malloc(neededBufSize); bufSize = neededBufSize; - FUZZ_ASSERT(cBuf && rBuf); } if (!cctx) { cctx = ZSTD_createCCtx(); @@ -87,7 +88,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) cLevel); FUZZ_ZASSERT(result); FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); } FUZZ_dataProducer_free(producer); #ifndef STATEFUL_FUZZING diff --git a/tests/fuzz/dictionary_decompress.c b/tests/fuzz/dictionary_decompress.c index 55d2a57f18f..9944baa158b 100644 --- a/tests/fuzz/dictionary_decompress.c +++ b/tests/fuzz/dictionary_decompress.c @@ -55,8 +55,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size); - void* rBuf = malloc(bufSize); - FUZZ_ASSERT(rBuf); + void* rBuf = FUZZ_malloc(bufSize); if (ddict) { ZSTD_decompress_usingDDict(dctx, rBuf, bufSize, src, size, ddict); } else { diff --git a/tests/fuzz/dictionary_loader.c b/tests/fuzz/dictionary_loader.c index 5a211c5de4b..f1fdf4da9e6 100644 --- a/tests/fuzz/dictionary_loader.c +++ b/tests/fuzz/dictionary_loader.c @@ -79,11 +79,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) DEBUGLOG(2, "Dict content type %d", dct); DEBUGLOG(2, "Dict size %u", (unsigned)size); - void* const rBuf = malloc(size); - FUZZ_ASSERT(rBuf); + void* const rBuf = FUZZ_malloc(size); size_t const cBufSize = ZSTD_compressBound(size); - void* const cBuf = malloc(cBufSize); - FUZZ_ASSERT(cBuf); + void* const cBuf = FUZZ_malloc(cBufSize); size_t const cSize = compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix); @@ -95,7 +93,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) size_t const rSize = decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix); FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); out: free(cBuf); diff --git a/tests/fuzz/dictionary_round_trip.c b/tests/fuzz/dictionary_round_trip.c index ce3cd672797..cd38178d6ae 100644 --- a/tests/fuzz/dictionary_round_trip.c +++ b/tests/fuzz/dictionary_round_trip.c @@ -84,7 +84,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) size = FUZZ_dataProducer_reserveDataPrefix(producer); size_t const rBufSize = size; - void* rBuf = malloc(rBufSize); + void* rBuf = FUZZ_malloc(rBufSize); size_t cBufSize = ZSTD_compressBound(size) * 2; void *cBuf; /* Half of the time fuzz with a 1 byte smaller output size. @@ -92,7 +92,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) * giving us 4 bytes of overhead. */ cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1); - cBuf = malloc(cBufSize); + cBuf = FUZZ_malloc(cBufSize); if (!cctx) { cctx = ZSTD_createCCtx(); @@ -108,7 +108,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer); FUZZ_ZASSERT(result); FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); } free(rBuf); free(cBuf); diff --git a/tests/fuzz/fuzz_data_producer.c b/tests/fuzz/fuzz_data_producer.c index 00bb0a3b21b..6518af30900 100644 --- a/tests/fuzz/fuzz_data_producer.c +++ b/tests/fuzz/fuzz_data_producer.c @@ -16,9 +16,7 @@ struct FUZZ_dataProducer_s{ }; FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size) { - FUZZ_dataProducer_t *producer = malloc(sizeof(FUZZ_dataProducer_t)); - - FUZZ_ASSERT(producer != NULL); + FUZZ_dataProducer_t *producer = FUZZ_malloc(sizeof(FUZZ_dataProducer_t)); producer->data = data; producer->size = size; diff --git a/tests/fuzz/fuzz_helpers.c b/tests/fuzz/fuzz_helpers.c new file mode 100644 index 00000000000..b80dc75716d --- /dev/null +++ b/tests/fuzz/fuzz_helpers.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-2020, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +#include "fuzz_helpers.h" + +#include +#include +#include + +void* FUZZ_malloc(size_t size) +{ + if (size > 0) { + void* const mem = malloc(size); + FUZZ_ASSERT(mem); + return mem; + } + return NULL; +} + +int FUZZ_memcmp(void const* lhs, void const* rhs, size_t size) +{ + if (size == 0) { + return 0; + } + return memcmp(lhs, rhs, size); +} \ No newline at end of file diff --git a/tests/fuzz/fuzz_helpers.h b/tests/fuzz/fuzz_helpers.h index 1420a65d2ce..cde2c4ea7cf 100644 --- a/tests/fuzz/fuzz_helpers.h +++ b/tests/fuzz/fuzz_helpers.h @@ -56,6 +56,17 @@ extern "C" { #define FUZZ_STATIC static #endif +/** + * malloc except return NULL for zero sized data and FUZZ_ASSERT + * that malloc doesn't fail. + */ +void* FUZZ_malloc(size_t size); + +/** + * memcmp but accepts NULL. + */ +int FUZZ_memcmp(void const* lhs, void const* rhs, size_t size); + #ifdef __cplusplus } #endif diff --git a/tests/fuzz/simple_compress.c b/tests/fuzz/simple_compress.c index f155e3b1c38..b64f373eb8a 100644 --- a/tests/fuzz/simple_compress.c +++ b/tests/fuzz/simple_compress.c @@ -41,8 +41,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) FUZZ_ASSERT(cctx); } - void *rBuf = malloc(bufSize); - FUZZ_ASSERT(rBuf); + void *rBuf = FUZZ_malloc(bufSize); ZSTD_compressCCtx(cctx, rBuf, bufSize, src, size, cLevel); free(rBuf); FUZZ_dataProducer_free(producer); diff --git a/tests/fuzz/simple_decompress.c b/tests/fuzz/simple_decompress.c index 8c404d13900..c3903ce8bfa 100644 --- a/tests/fuzz/simple_decompress.c +++ b/tests/fuzz/simple_decompress.c @@ -35,8 +35,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) } size_t const bufSize = FUZZ_dataProducer_uint32Range(producer, 0, 10 * size); - void *rBuf = malloc(bufSize); - FUZZ_ASSERT(rBuf); + void *rBuf = FUZZ_malloc(bufSize); ZSTD_decompressDCtx(dctx, rBuf, bufSize, src, size); free(rBuf); diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c index 41ea96739fe..348da03a962 100644 --- a/tests/fuzz/simple_round_trip.c +++ b/tests/fuzz/simple_round_trip.c @@ -70,7 +70,7 @@ static size_t roundTripTest(void *result, size_t resultCapacity, int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { size_t const rBufSize = size; - void* rBuf = malloc(rBufSize); + void* rBuf = FUZZ_malloc(rBufSize); size_t cBufSize = ZSTD_compressBound(size); void* cBuf; @@ -85,9 +85,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) */ cBufSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1); - cBuf = malloc(cBufSize); - - FUZZ_ASSERT(cBuf && rBuf); + cBuf = FUZZ_malloc(cBufSize); if (!cctx) { cctx = ZSTD_createCCtx(); @@ -103,7 +101,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) roundTripTest(rBuf, rBufSize, cBuf, cBufSize, src, size, producer); FUZZ_ZASSERT(result); FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); } free(rBuf); free(cBuf); diff --git a/tests/fuzz/stream_decompress.c b/tests/fuzz/stream_decompress.c index 503d32d6614..25901b1eb37 100644 --- a/tests/fuzz/stream_decompress.c +++ b/tests/fuzz/stream_decompress.c @@ -76,9 +76,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) /* Allocate all buffers and contexts if not already allocated */ if (!buf) { - buf = malloc(kBufSize); - FUZZ_ASSERT(buf); - } + buf = FUZZ_malloc(kBufSize); + } if (!dstream) { dstream = ZSTD_createDStream(); @@ -99,7 +98,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) ZSTD_inBuffer in = makeInBuffer(&src, &size, producer, prevInWasZero ? 1 : 0); prevInWasZero = in.size == 0; while (in.pos != in.size) { - if (!stableOutBuffer || FUZZ_dataProducer_uint32Range(producer, 0, 100) == 55) { + if (!stableOutBuffer || prevOutWasZero || FUZZ_dataProducer_uint32Range(producer, 0, 100) == 55) { out = makeOutBuffer(producer, prevOutWasZero ? 1 : 0); } prevOutWasZero = out.size == 0; diff --git a/tests/fuzz/stream_round_trip.c b/tests/fuzz/stream_round_trip.c index e060950f016..286d3871b7a 100644 --- a/tests/fuzz/stream_round_trip.c +++ b/tests/fuzz/stream_round_trip.c @@ -146,10 +146,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) if (neededBufSize > bufSize) { free(cBuf); free(rBuf); - cBuf = (uint8_t*)malloc(neededBufSize); - rBuf = (uint8_t*)malloc(neededBufSize); + cBuf = (uint8_t*)FUZZ_malloc(neededBufSize); + rBuf = (uint8_t*)FUZZ_malloc(neededBufSize); bufSize = neededBufSize; - FUZZ_ASSERT(cBuf && rBuf); } if (!cctx) { cctx = ZSTD_createCCtx(); @@ -166,7 +165,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize); FUZZ_ZASSERT(rSize); FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); } FUZZ_dataProducer_free(producer); diff --git a/tests/fuzz/zstd_frame_info.c b/tests/fuzz/zstd_frame_info.c index 16a28d6903a..876a74e9aeb 100644 --- a/tests/fuzz/zstd_frame_info.c +++ b/tests/fuzz/zstd_frame_info.c @@ -22,6 +22,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) { ZSTD_frameHeader zfh; + if (size == 0) { + src = NULL; + } /* You can fuzz any helper functions here that are fast, and take zstd * compressed data as input. E.g. don't expect the input to be a dictionary, * so don't fuzz ZSTD_getDictID_fromDict(). diff --git a/tests/fuzz/zstd_helpers.c b/tests/fuzz/zstd_helpers.c index 8294f6fe235..5680bd628e1 100644 --- a/tests/fuzz/zstd_helpers.c +++ b/tests/fuzz/zstd_helpers.c @@ -106,14 +106,13 @@ FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *pro { size_t const dictSize = MAX(srcSize / 8, 1024); size_t const totalSampleSize = dictSize * 11; - FUZZ_dict_t dict = { malloc(dictSize), dictSize }; - char* const samples = (char*)malloc(totalSampleSize); + FUZZ_dict_t dict = { FUZZ_malloc(dictSize), dictSize }; + char* const samples = (char*)FUZZ_malloc(totalSampleSize); unsigned nbSamples = 100; - size_t* const samplesSizes = (size_t*)malloc(sizeof(size_t) * nbSamples); + size_t* const samplesSizes = (size_t*)FUZZ_malloc(sizeof(size_t) * nbSamples); size_t pos = 0; size_t sample = 0; ZDICT_fastCover_params_t params; - FUZZ_ASSERT(dict.buff && samples && samplesSizes); for (sample = 0; sample < nbSamples; ++sample) { size_t const remaining = totalSampleSize - pos; @@ -123,7 +122,6 @@ FUZZ_dict_t FUZZ_train(void const* src, size_t srcSize, FUZZ_dataProducer_t *pro memcpy(samples + pos, src + offset, toCopy); pos += toCopy; samplesSizes[sample] = toCopy; - } memset(samples + pos, 0, totalSampleSize - pos); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 233468106a4..c9cf85bdbe4 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -538,6 +538,12 @@ static int basicUnitTests(U32 const seed, double compressibility) if (ZSTD_getErrorCode(r) != ZSTD_error_srcSize_wrong) goto _output_error; } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : decompress into NULL buffer : ", testNb++); + { size_t const r = ZSTD_decompress(NULL, 0, compressedBuffer, compressedBufferSize); + if (!ZSTD_isError(r)) goto _output_error; + if (ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall) goto _output_error; } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++); { /* create compressed buffer with content size missing */ ZSTD_CCtx* const cctx = ZSTD_createCCtx(); From 54144285fd205a533089559468865ace5a7afad1 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 7 May 2020 05:01:27 -0700 Subject: [PATCH 339/402] small speed improvement for strategy fast gcc 9.3.0 : kennedy : 459 -> 466 silesia : 360 -> 365 enwik8 : 267 -> 269 clang 10.0.0 : kennedy : 436 -> 441 silesia : 364 -> 366 enwik8 : 271 -> 272 --- lib/compress/zstd_fast.c | 41 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index bfe4e10227e..81c7cd2c808 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -81,9 +81,9 @@ ZSTD_compressBlock_fast_generic( /* Main Search Loop */ #ifdef __INTEL_COMPILER - /* From intel 'The vector pragma indicates that the loop should be - * vectorized if it is legal to do so'. Can be used together with - * #pragma ivdep (but have opted to exclude that because intel + /* From intel 'The vector pragma indicates that the loop should be + * vectorized if it is legal to do so'. Can be used together with + * #pragma ivdep (but have opted to exclude that because intel * warns against using it).*/ #pragma vector always #endif @@ -98,7 +98,7 @@ ZSTD_compressBlock_fast_generic( U32 const current1 = (U32)(ip1-base); U32 const matchIndex0 = hashTable[h0]; U32 const matchIndex1 = hashTable[h1]; - BYTE const* repMatch = ip2-offset_1; + BYTE const* repMatch = ip2 - offset_1; const BYTE* match0 = base + matchIndex0; const BYTE* match1 = base + matchIndex1; U32 offcode; @@ -113,9 +113,10 @@ ZSTD_compressBlock_fast_generic( assert(ip0 + 1 == ip1); if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) { - mLength = ip2[-1] == repMatch[-1] ? 1 : 0; + mLength = (ip2[-1] == repMatch[-1]) ? 1 : 0; ip0 = ip2 - mLength; match0 = repMatch - mLength; + mLength += 4; offcode = 0; goto _match; } @@ -140,19 +141,18 @@ ZSTD_compressBlock_fast_generic( offset_2 = offset_1; offset_1 = (U32)(ip0-match0); offcode = offset_1 + ZSTD_REP_MOVE; - mLength = 0; + mLength = 4; /* Count the backwards match length */ while (((ip0>anchor) & (match0>prefixStart)) && (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */ _match: /* Requires: ip0, match0, offcode */ /* Count the forward length */ - mLength += ZSTD_count(ip0+mLength+4, match0+mLength+4, iend) + 4; + mLength += ZSTD_count(ip0+mLength, match0+mLength, iend); ZSTD_storeSeq(seqStore, (size_t)(ip0-anchor), anchor, iend, offcode, mLength-MINMATCH); /* match found */ ip0 += mLength; anchor = ip0; - ip1 = ip0 + 1; if (ip0 <= ilimit) { /* Fill Table */ @@ -160,19 +160,18 @@ ZSTD_compressBlock_fast_generic( hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */ hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base); - while ( ((ip0 <= ilimit) & (offset_2>0)) /* offset_2==0 means offset_2 is invalidated */ - && (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) ) { - /* store sequence */ - size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4; - { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */ - hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base); - ip0 += rLength; - ip1 = ip0 + 1; - ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, 0 /*offCode*/, rLength-MINMATCH); - anchor = ip0; - continue; /* faster when present (confirmed on gcc-8) ... (?) */ - } - } + if (offset_2 > 0) { /* offset_2==0 means offset_2 is invalidated */ + while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) ) { + /* store sequence */ + size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4; + { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */ + hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base); + ip0 += rLength; + ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, 0 /*offCode*/, rLength-MINMATCH); + anchor = ip0; + continue; /* faster when present (confirmed on gcc-8) ... (?) */ + } } } + ip1 = ip0 + 1; } /* save reps for next block */ From cf854f4660bfc7814c1a8e1b25d33eb21ff4a9de Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 7 May 2020 07:59:56 -0700 Subject: [PATCH 340/402] support for verbose make A commonly accepted makefile idiom is V=1 or VERBOSE=1 to request the printing of all commands. This is not "default" though, and must be manually added. Example : Before : ``` make libzstd compiling dynamic library 1.4.5 creating versioned links make libzstd V=1 compiling dynamic library 1.4.5 creating versioned links ``` After : ``` make libzstd compiling dynamic library 1.4.5 creating versioned links make libzstd V=1 compiling dynamic library 1.4.5 cc -DXXH_NAMESPACE=ZSTD_ -DZSTD_LEGACY_SUPPORT=5 -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes -Wundef -Wpointer-arith -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings -Wredundant-decls -Wmissing-prototypes -Wc++-compat -O3 common/debug.c common/entropy_common.c common/error_private.c common/fse_decompress.c common/pool.c common/threading.c common/xxhash.c common/zstd_common.c compress/fse_compress.c compress/hist.c compress/huf_compress.c compress/zstd_compress.c compress/zstd_compress_literals.c compress/zstd_compress_sequences.c compress/zstd_compress_superblock.c compress/zstd_double_fast.c compress/zstd_fast.c compress/zstd_lazy.c compress/zstd_ldm.c compress/zstd_opt.c compress/zstdmt_compress.c decompress/huf_decompress.c decompress/zstd_ddict.c decompress/zstd_decompress.c decompress/zstd_decompress_block.c deprecated/zbuff_common.c deprecated/zbuff_compress.c deprecated/zbuff_decompress.c dictBuilder/cover.c dictBuilder/divsufsort.c dictBuilder/fastcover.c dictBuilder/zdict.c legacy/zstd_v05.c legacy/zstd_v06.c legacy/zstd_v07.c -shared -fPIC -fvisibility=hidden -Wl,-soname=libzstd.so.1 -o libzstd.so.1.4.5 creating versioned links ln -sf libzstd.so.1.4.5 libzstd.so.1 ln -sf libzstd.so.1.4.5 libzstd.so ``` --- lib/Makefile | 73 ++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 4e3598accff..40861ed9f50 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -8,6 +8,8 @@ # You may select, at your option, one of the above-listed licenses. # ################################################################ +Q = $(if $(filter 1,$(V) $(VERBOSE)),,@) + # Version numbers LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h` LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h` @@ -178,7 +180,7 @@ all: lib libzstd.a: ARFLAGS = rcs libzstd.a: $(ZSTD_OBJ) @echo compiling static library - @$(AR) $(ARFLAGS) $@ $^ + $(Q)$(AR) $(ARFLAGS) $@ $^ ifneq (,$(filter Windows%,$(OS))) @@ -193,23 +195,26 @@ LIBZSTD = libzstd.$(SHARED_EXT_VER) $(LIBZSTD): LDFLAGS += -shared -fPIC -fvisibility=hidden $(LIBZSTD): $(ZSTD_FILES) @echo compiling dynamic library $(LIBVER) - @$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@ + $(Q)$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@ @echo creating versioned links - @ln -sf $@ libzstd.$(SHARED_EXT_MAJOR) - @ln -sf $@ libzstd.$(SHARED_EXT) + $(Q)ln -sf $@ libzstd.$(SHARED_EXT_MAJOR) + $(Q)ln -sf $@ libzstd.$(SHARED_EXT) endif - +.PHONY: libzstd libzstd : $(LIBZSTD) +.PHONY: lib lib : libzstd.a libzstd +.PHONY: lib-mt %-mt : CPPFLAGS += -DZSTD_MULTITHREAD %-mt : LDFLAGS += -pthread %-mt : % @echo multi-threading build completed +.PHONY: lib-release %-release : DEBUGFLAGS := %-release : % @echo release build completed @@ -222,17 +227,17 @@ libzstd-nomt: LDFLAGS += -shared -fPIC -fvisibility=hidden libzstd-nomt: $(ZSTD_NOMT_FILES) @echo compiling single-thread dynamic library $(LIBVER) @echo files : $(ZSTD_NOMT_FILES) - @$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@ + $(Q)$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@ clean: - @$(RM) -r *.dSYM # macOS-specific - @$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc - @$(RM) dll/libzstd.dll dll/libzstd.lib libzstd-nomt* - @$(RM) common/*.o compress/*.o decompress/*.o dictBuilder/*.o legacy/*.o deprecated/*.o + $(Q)$(RM) -r *.dSYM # macOS-specific + $(Q)$(RM) core *.o *.a *.gcda *.$(SHARED_EXT) *.$(SHARED_EXT).* libzstd.pc + $(Q)$(RM) dll/libzstd.dll dll/libzstd.lib libzstd-nomt* + $(Q)$(RM) common/*.o compress/*.o decompress/*.o dictBuilder/*.o legacy/*.o deprecated/*.o @echo Cleaning library completed #----------------------------------------------------------------------------- -# make install is validated only for Linux, macOS, BSD, Hurd and Solaris targets +# make install is validated only for below listed environments #----------------------------------------------------------------------------- ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku)) @@ -267,7 +272,7 @@ INSTALL_DATA ?= $(INSTALL) -m 644 libzstd.pc: libzstd.pc: libzstd.pc.in @echo creating pkgconfig - @sed -e 's|@PREFIX@|$(PREFIX)|' \ + $(Q)sed -e 's|@PREFIX@|$(PREFIX)|' \ -e 's|@VERSION@|$(VERSION)|' \ $< >$@ @@ -275,39 +280,39 @@ install: install-pc install-static install-shared install-includes @echo zstd static and shared library installed install-pc: libzstd.pc - @$(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/ - @$(INSTALL_DATA) libzstd.pc $(DESTDIR)$(PKGCONFIGDIR)/ + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/ + $(Q)$(INSTALL_DATA) libzstd.pc $(DESTDIR)$(PKGCONFIGDIR)/ install-static: libzstd.a @echo Installing static library - @$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/ - @$(INSTALL_DATA) libzstd.a $(DESTDIR)$(LIBDIR) + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/ + $(Q)$(INSTALL_DATA) libzstd.a $(DESTDIR)$(LIBDIR) install-shared: libzstd @echo Installing shared library - @$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/ - @$(INSTALL_PROGRAM) $(LIBZSTD) $(DESTDIR)$(LIBDIR) - @ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) - @ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT) + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)/ + $(Q)$(INSTALL_PROGRAM) $(LIBZSTD) $(DESTDIR)$(LIBDIR) + $(Q)ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) + $(Q)ln -sf $(LIBZSTD) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT) install-includes: @echo Installing includes - @$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/ - @$(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR) - @$(INSTALL_DATA) common/zstd_errors.h $(DESTDIR)$(INCLUDEDIR) - @$(INSTALL_DATA) deprecated/zbuff.h $(DESTDIR)$(INCLUDEDIR) # prototypes generate deprecation warnings - @$(INSTALL_DATA) dictBuilder/zdict.h $(DESTDIR)$(INCLUDEDIR) + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/ + $(Q)$(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR) + $(Q)$(INSTALL_DATA) common/zstd_errors.h $(DESTDIR)$(INCLUDEDIR) + $(Q)$(INSTALL_DATA) deprecated/zbuff.h $(DESTDIR)$(INCLUDEDIR) # prototypes generate deprecation warnings + $(Q)$(INSTALL_DATA) dictBuilder/zdict.h $(DESTDIR)$(INCLUDEDIR) uninstall: - @$(RM) $(DESTDIR)$(LIBDIR)/libzstd.a - @$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT) - @$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) - @$(RM) $(DESTDIR)$(LIBDIR)/$(LIBZSTD) - @$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc - @$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h - @$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h - @$(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h # Deprecated streaming functions - @$(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libzstd.a + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT) + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libzstd.$(SHARED_EXT_MAJOR) + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/$(LIBZSTD) + $(Q)$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/zbuff.h # Deprecated streaming functions + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h @echo zstd libraries successfully uninstalled endif From 1b1cc3d1b7e13aacd07de982dea323253052ab36 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 7 May 2020 10:38:06 -0500 Subject: [PATCH 341/402] adding some static-anslysis docs --- CONTRIBUTING.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02834659c62..23d62c099ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,6 +70,8 @@ Our contribution process works in three main stages: * Ensure CI tests pass: * Before sharing anything to the community, make sure that all CI tests pass on your local fork. See our section on setting up your CI environment for more information on how to do this. + * Ensure that static analysis passes on your development machine. See the Static Analysis section + below to see how to do this. * Create a pull request: * When you are ready to share you changes to the community, create a pull request from your branch to facebook:dev. You can do this very easily by clicking 'Create Pull Request' on your fork's home @@ -106,6 +108,24 @@ Our contribution process works in three main stages: their change makes it to the next release of zstd. Users will often discover bugs in your code or suggest ways to refine and improve your initial changes even after the pull request is merged. +## Static Analysis +Static analysis is a process for examining the correctness or validity of a program without actually +executing it. It usually helps us find many simple bugs. Zstd uses clang's `scan-build` tool for +static analysis. You can install it by following the instructions for your OS on https://clang-analyzer.llvm.org/scan-build. + +Once installed, you can ensure that our static analysis tests pass on your local development machine +by running: +``` +make staticAnalyze +``` + +In general, you can use `scan-build` to static analyze any build script. For example, to static analyze +just `contrib/largeNbDicts` and nothing else, you can run: + +``` +scan-build make -C contrib/largeNbDicts largeNbDicts +``` + ## Setting up continuous integration (CI) on your fork Zstd uses a number of different continuous integration (CI) tools to ensure that new changes are well tested before they make it to an official release. Specifically, we use the platforms From 45c66dd298a40e969a0fe6d410fde84fd8a96697 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Wed, 6 May 2020 18:51:14 -0700 Subject: [PATCH 342/402] [zdict] Stabilize ZDICT_finalizeDictionary() --- lib/dictBuilder/zdict.h | 76 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index 53f58d7ac2f..ff2e77faf77 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -61,6 +61,53 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples); +typedef struct { + int compressionLevel; /*< optimize for a specific zstd compression level; 0 means default */ + unsigned notificationLevel; /*< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ + unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value) */ +} ZDICT_params_t; + +/*! ZDICT_finalizeDictionary(): + * Given a custom content as a basis for dictionary, and a set of samples, + * finalize dictionary by adding headers and statistics according to the zstd + * dictionary format. + * + * Samples must be stored concatenated in a flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each + * sample in order. The samples are used to construct the statistics, so they + * should be representative of what you will compress with this dictionary. + * + * The compression level can be set in `parameters`. You should pass the + * compression level you expect to use in production. The statistics for each + * compression level differ, so tuning the dictionary for the compression level + * can help quite a bit. + * + * You can set an explicit dictionary ID in `parameters`, or allow us to pick + * a random dictionary ID for you, but we can't guarantee no collisions. + * + * The dstDictBuffer and the dictContent may overlap, and the content will be + * appended to the end of the header. If the header + the content doesn't fit in + * maxDictSize the beginning of the content is truncated to make room, since it + * is presumed that the most profitable content is at the end of the dictionary, + * since that is the cheapest to reference. + * + * `dictContentSize` must be >= ZDICT_CONTENTSIZE_MIN bytes. + * `maxDictSize` must be >= max(dictContentSize, ZSTD_DICTSIZE_MIN). + * + * @return: size of dictionary stored into `dstDictBuffer` (<= `maxDictSize`), + * or an error code, which can be tested by ZDICT_isError(). + * Note: ZDICT_finalizeDictionary() will push notifications into stderr if + * instructed to, using notificationLevel>0. + * NOTE: This function currently may fail in several edge cases including: + * * Not enough samples + * * Samples are uncompressible + * * Samples are all exactly the same + */ +ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dstDictBuffer, size_t maxDictSize, + const void* dictContent, size_t dictContentSize, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_params_t parameters); + /*====== Helper functions ======*/ ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ @@ -79,11 +126,8 @@ ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); * Use them only in association with static linking. * ==================================================================================== */ -typedef struct { - int compressionLevel; /* optimize for a specific zstd compression level; 0 means default */ - unsigned notificationLevel; /* Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ - unsigned dictID; /* force dictID value; 0 means auto mode (32-bits random value) */ -} ZDICT_params_t; +#define ZDICT_CONTENTSIZE_MIN 128 +#define ZDICT_DICTSIZE_MIN 256 /*! ZDICT_cover_params_t: * k and d are the only required parameters. @@ -199,28 +243,6 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer, const size_t* samplesSizes, unsigned nbSamples, ZDICT_fastCover_params_t* parameters); -/*! ZDICT_finalizeDictionary(): - * Given a custom content as a basis for dictionary, and a set of samples, - * finalize dictionary by adding headers and statistics. - * - * Samples must be stored concatenated in a flat buffer `samplesBuffer`, - * supplied with an array of sizes `samplesSizes`, providing the size of each sample in order. - * - * dictContentSize must be >= ZDICT_CONTENTSIZE_MIN bytes. - * maxDictSize must be >= dictContentSize, and must be >= ZDICT_DICTSIZE_MIN bytes. - * - * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`), - * or an error code, which can be tested by ZDICT_isError(). - * Note: ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0. - * Note 2: dictBuffer and dictContent can overlap - */ -#define ZDICT_CONTENTSIZE_MIN 128 -#define ZDICT_DICTSIZE_MIN 256 -ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity, - const void* dictContent, size_t dictContentSize, - const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, - ZDICT_params_t parameters); - typedef struct { unsigned selectivityLevel; /* 0 means default; larger => select more => larger dictionary */ ZDICT_params_t zParams; From 37d10b6c75cb2731dd069590f326cd842a5e5f80 Mon Sep 17 00:00:00 2001 From: Mingye Wang Date: Fri, 8 May 2020 02:52:18 +0800 Subject: [PATCH 343/402] programs/README.md: update help text I noticed that the help is outdated as there is no mention of --adapt. Y'all should probably put "update help text" into your release checklist. --- programs/README.md | 80 ++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/programs/README.md b/programs/README.md index 7668d49a207..7ae7822d48e 100644 --- a/programs/README.md +++ b/programs/README.md @@ -121,55 +121,66 @@ The `-i` parameter selects minimal time used for each of tested levels. #### Usage of Command Line Interface The full list of options can be obtained with `-h` or `-H` parameter: ``` -Usage : - zstd [args] [FILE(s)] [-o file] +Usage : + zstd [args] [FILE(s)] [-o file] -FILE : a filename +FILE : a filename with no FILE, or when FILE is - , read standard input -Arguments : - -# : # compression level (1-19, default: 3) - -d : decompression - -D file: use `file` as Dictionary - -o file: result stored into `file` (only if 1 input file) - -f : overwrite output without prompting and (de)compress links ---rm : remove source file(s) after successful de/compression - -k : preserve source file(s) (default) - -h/-H : display help/long help and exit - -Advanced arguments : - -V : display Version number and exit +Arguments : + -# : # compression level (1-19, default: 3) + -d : decompression + -D file: use `file` as Dictionary + -o file: result stored into `file` (only if 1 input file) + -f : overwrite output without prompting and (de)compress links +--rm : remove source file(s) after successful de/compression + -k : preserve source file(s) (default) + -h/-H : display help/long help and exit + +Advanced arguments : + -V : display Version number and exit -v : verbose mode; specify multiple times to increase verbosity -q : suppress warnings; specify twice to suppress errors too -c : force write to standard output, even if it is the console - -l : print information about zstd compressed files + -l : print information about zstd compressed files +--exclude-compressed: only compress files that are not previously compressed --ultra : enable levels beyond 19, up to 22 (requires more memory) ---long : enable long distance matching (requires more memory) +--long[=#]: enable long distance matching with given window log (default: 27) +--fast[=#]: switch to very fast compression levels (default: 1) +--adapt : dynamically adapt compression level to I/O conditions +--stream-size=# : optimize compression parameters for streaming input of given number of bytes +--size-hint=# optimize compression parameters for streaming input of approximately this size +--target-compressed-block-size=# : make compressed block near targeted size + -T# : spawns # compression threads (default: 1, 0==# cores) + -B# : select size of each job (default: 0==automatic) +--rsyncable : compress using a rsync-friendly method (-B sets block size) --no-dictID : don't write dictID into header (dictionary compression) ---[no-]check : integrity check (default: enabled) - -r : operate recursively on directories ---format=gzip : compress files to the .gz format ---format=xz : compress files to the .xz format ---format=lzma : compress files to the .lzma format ---test : test compressed file integrity +--[no-]check : integrity check (default: enabled) +--[no-]compress-literals : force (un)compressed literals + -r : operate recursively on directories +--output-dir-flat[=directory]: all resulting files stored into `directory`. +--format=zstd : compress files to the .zst format (default) +--format=gzip : compress files to the .gz format +--test : test compressed file integrity --[no-]sparse : sparse mode (default: disabled) - -M# : Set a memory usage limit for decompression --- : All arguments after "--" are treated as files + -M# : Set a memory usage limit for decompression +--no-progress : do not display the progress bar +-- : All arguments after "--" are treated as files -Dictionary builder : ---train ## : create a dictionary from a training set of files +Dictionary builder : +--train ## : create a dictionary from a training set of files --train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args ---train-fastcover[=k=#,d=#,f=#,steps=#,split=#,shrink[=#],accel=#] : use the fastcover algorithm with optional args +--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args --train-legacy[=s=#] : use the legacy algorithm with selectivity (default: 9) - -o file : `file` is dictionary name (default: dictionary) ---maxdict=# : limit dictionary to specified size (default: 112640) + -o file : `file` is dictionary name (default: dictionary) +--maxdict=# : limit dictionary to specified size (default: 112640) --dictID=# : force dictionary ID to specified value (default: random) -Benchmark arguments : - -b# : benchmark file(s), using # compression level (default: 3) +Benchmark arguments : + -b# : benchmark file(s), using # compression level (default: 3) -e# : test all compression levels from -bX to # (default: 1) - -i# : minimum evaluation time in seconds (default: 3s) + -i# : minimum evaluation time in seconds (default: 3s) -B# : cut file into independent blocks of size # (default: no block) ---priority=rt : set process priority to real-time +--priority=rt : set process priority to real-time ``` #### Restricted usage of Environment Variables @@ -232,7 +243,6 @@ The below table illustrates this on the [Silesia compression corpus]. | `zstd -10` | `3.523` | `16.4 MB/s` | `489.2 MB/s` | | `zstd -10 --long`| `3.566` | `16.2 MB/s` | `415.7 MB/s` | - #### zstdgrep `zstdgrep` is a utility which makes it possible to `grep` directly a `.zst` compressed file. From b2e56f7f7f7735b0f385a7f14ae42b74172603e0 Mon Sep 17 00:00:00 2001 From: caoyzh Date: Mon, 16 Mar 2020 11:07:31 +0800 Subject: [PATCH 344/402] Optimize compression by using neon function. --- lib/common/zstd_internal.h | 21 +++++++++++++++++++-- lib/compress/zstd_compress.c | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index bd08de82120..745a1d0ce88 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -21,6 +21,9 @@ ***************************************/ #include "compiler.h" #include "mem.h" +#ifdef __aarch64__ +#include "arm_neon.h" +#endif #include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ #include "error_private.h" #define ZSTD_STATIC_LINKING_ONLY @@ -224,10 +227,22 @@ static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; /*-******************************************* * Shared functions to include for inlining *********************************************/ -static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } +static void ZSTD_copy8(void* dst, const void* src) { +#ifdef __aarch64__ + vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src)); +#else + memcpy(dst, src, 8); +#endif +} #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } -static void ZSTD_copy16(void* dst, const void* src) { memcpy(dst, src, 16); } +static void ZSTD_copy16(void* dst, const void* src) { +#ifdef __aarch64__ + vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src)); +#else + memcpy(dst, src, 16); +#endif +} #define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; } #define WILDCOPY_OVERLENGTH 32 @@ -269,8 +284,10 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e * one COPY16() in the first call. Then, do two calls per loop since * at that point it is more likely to have a high trip count. */ +#ifndef __aarch64__ COPY16(op, ip); if (op >= oend) return; +#endif do { COPY16(op, ip); COPY16(op, ip); diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ff8a00e6b3b..b2830b01e86 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1865,6 +1865,20 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa for (rowNb=0 ; rowNb < nbRows ; rowNb++) { int column; +#ifdef __aarch64__ + for (column=0; column Date: Sat, 28 Mar 2020 00:11:50 +0800 Subject: [PATCH 345/402] Change "arm_neon.h" to system include --- lib/common/zstd_internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 745a1d0ce88..0f131103322 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -19,11 +19,11 @@ /*-************************************* * Dependencies ***************************************/ -#include "compiler.h" -#include "mem.h" #ifdef __aarch64__ -#include "arm_neon.h" +#include #endif +#include "compiler.h" +#include "mem.h" #include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ #include "error_private.h" #define ZSTD_STATIC_LINKING_ONLY From 9e802ede9c3a6030460360e78821668e67c974f3 Mon Sep 17 00:00:00 2001 From: caoyzh Date: Thu, 2 Apr 2020 23:08:13 +0800 Subject: [PATCH 346/402] Modify indent of comments --- lib/common/zstd_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 0f131103322..009d8427c1f 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -281,8 +281,8 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e /* Separate out the first COPY16() call because the copy length is * almost certain to be short, so the branches have different * probabilities. Since it is almost certain to be short, only do - * one COPY16() in the first call. Then, do two calls per loop since - * at that point it is more likely to have a high trip count. + * one COPY16() in the first call. Then, do two calls per loop since + * at that point it is more likely to have a high trip count. */ #ifndef __aarch64__ COPY16(op, ip); From a7e34ff693483177948fed563105a11843e9f590 Mon Sep 17 00:00:00 2001 From: caoyzh Date: Tue, 14 Apr 2020 21:29:43 +0800 Subject: [PATCH 347/402] revert ZSTD_reduceTable_internal()'s modificatiion --- lib/compress/zstd_compress.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index b2830b01e86..ff8a00e6b3b 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1865,20 +1865,6 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa for (rowNb=0 ; rowNb < nbRows ; rowNb++) { int column; -#ifdef __aarch64__ - for (column=0; column Date: Tue, 14 Apr 2020 21:33:25 +0800 Subject: [PATCH 348/402] Change the modification of ZSTD_wildcopy() --- lib/common/zstd_internal.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/common/zstd_internal.h b/lib/common/zstd_internal.h index 009d8427c1f..3bc7e55a0a9 100644 --- a/lib/common/zstd_internal.h +++ b/lib/common/zstd_internal.h @@ -285,14 +285,19 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e * at that point it is more likely to have a high trip count. */ #ifndef __aarch64__ + do { + COPY16(op, ip); + } + while (op < oend); +#else COPY16(op, ip); if (op >= oend) return; -#endif do { COPY16(op, ip); COPY16(op, ip); } while (op < oend); +#endif } } From df9e5b6f4c1ecd0497a14cb0120dd57568d5d0c4 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Thu, 7 May 2020 22:07:40 -0500 Subject: [PATCH 349/402] adding --- Makefile | 11 ++++++++++- lib/Makefile | 13 +++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index beca1567616..14419feabac 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,16 @@ FUZZDIR = $(TESTDIR)/fuzz # Define nul output VOID = /dev/null -ifneq (,$(filter Windows%,$(OS))) +# When cross-compiling from linux to windows, you might +# need to specify this as "Windows." Fedora build fails +# without it. +# +# Note: mingw-w64 build from linux to windows does not +# fail on other tested distros (ubuntu, debian) even +# without manually specifying the TARGET_SYSTEM. +TARGET_SYSTEM ?= $(OS) + +ifneq (,$(filter Windows%,$(TARGET_SYSTEM))) EXT =.exe else EXT = diff --git a/lib/Makefile b/lib/Makefile index 40861ed9f50..e1c9e6c0b0a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -10,6 +10,15 @@ Q = $(if $(filter 1,$(V) $(VERBOSE)),,@) +# When cross-compiling from linux to windows, you might +# need to specify this as "Windows." Fedora build fails +# without it. +# +# Note: mingw-w64 build from linux to windows does not +# fail on other tested distros (ubuntu, debian) even +# without manually specifying the TARGET_SYSTEM. +TARGET_SYSTEM ?= $(OS) + # Version numbers LIBVER_MAJOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h` LIBVER_MINOR_SCRIPT:=`sed -n '/define ZSTD_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./zstd.h` @@ -23,7 +32,7 @@ VERSION?= $(LIBVER) CCVER := $(shell $(CC) --version) CPPFLAGS+= -DXXH_NAMESPACE=ZSTD_ -ifeq ($(OS),Windows_NT) # MinGW assumed +ifeq ($(TARGET_SYSTEM),Windows_NT) # MinGW assumed CPPFLAGS += -D__USE_MINGW_ANSI_STDIO # compatibility with %zu formatting endif DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ @@ -182,7 +191,7 @@ libzstd.a: $(ZSTD_OBJ) @echo compiling static library $(Q)$(AR) $(ARFLAGS) $@ $^ -ifneq (,$(filter Windows%,$(OS))) +ifneq (,$(filter Windows%,$(TARGET_SYSTEM))) LIBZSTD = dll\libzstd.dll $(LIBZSTD): $(ZSTD_FILES) From e873697625fa2a9f9a31c1851ebd15107b62c207 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 8 May 2020 10:51:37 -0700 Subject: [PATCH 350/402] updated documentation regarding ZSTD_CLEVEL make it clearer that it's useful for `tar --zstd`. --- programs/README.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/programs/README.md b/programs/README.md index 7668d49a207..a097cdac75c 100644 --- a/programs/README.md +++ b/programs/README.md @@ -10,7 +10,7 @@ There are however other Makefile targets that create different variations of CLI - `zstd-decompress` : version of CLI which can only decompress zstd format -#### Compilation variables +### Compilation variables `zstd` scope can be altered by modifying the following `make` variables : - __HAVE_THREAD__ : multithreading is automatically enabled when `pthread` is detected. @@ -69,11 +69,11 @@ There are however other Makefile targets that create different variations of CLI Example : `make zstd BACKTRACE=1` -#### Aggregation of parameters +### Aggregation of parameters CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`. -#### Symlink shortcuts +### Symlink shortcuts It's possible to invoke `zstd` through a symlink. When the name of the symlink has a specific value, it triggers an associated behavior. - `zstdmt` : compress using all cores available on local system. @@ -86,7 +86,7 @@ When the name of the symlink has a specific value, it triggers an associated beh - `ungz`, `unxz` and `unlzma` will do the same, and will also remove source file by default (use `--keep` to preserve). -#### Dictionary builder in Command Line Interface +### Dictionary builder in Command Line Interface Zstd offers a training mode, which can be used to tune the algorithm for a selected type of data, by providing it with a few samples. The result of the training is stored in a file selected with the `-o` option (default name is `dictionary`), @@ -106,7 +106,7 @@ Usage of the dictionary builder and created dictionaries with CLI: 3. Decompress with the dictionary: `zstd --decompress FILE.zst -D dictionaryName` -#### Benchmark in Command Line Interface +### Benchmark in Command Line Interface CLI includes in-memory compression benchmark module for zstd. The benchmark is conducted using given filenames. The files are read into memory and joined together. It makes benchmark more precise as it eliminates I/O overhead. @@ -118,7 +118,7 @@ One can select compression levels starting from `-b` and ending with `-e`. The `-i` parameter selects minimal time used for each of tested levels. -#### Usage of Command Line Interface +### Usage of Command Line Interface The full list of options can be obtained with `-h` or `-H` parameter: ``` Usage : @@ -172,16 +172,19 @@ Benchmark arguments : --priority=rt : set process priority to real-time ``` -#### Restricted usage of Environment Variables -Using environment variables to set parameters has security implications. -Therefore, this avenue is intentionally restricted. -Only `ZSTD_CLEVEL` is supported currently, for setting compression level. -`ZSTD_CLEVEL` can be used to set the level between 1 and 19 (the "normal" range). -If the value of `ZSTD_CLEVEL` is not a valid integer, it will be ignored with a warning message. -`ZSTD_CLEVEL` just replaces the default compression level (`3`). -It can be overridden by corresponding command line arguments. +### Passing parameters through Environment Variables +`ZSTD_CLEVEL` can be used to modify the default compression level of `zstd` +(usually set to `3`) to another value between 1 and 19 (the "normal" range). +This can be useful when `zstd` CLI is invoked in a way that doesn't allow passing arguments. +One such scenario is `tar --zstd`. +As `ZSTD_CLEVEL` only replaces the default compression level, +it can then be overridden by corresponding command line arguments. -#### Long distance matching mode +There is no "generic" way to pass "any kind of parameter" to `zstd` in a pass-through manner. +Using environment variables for this purpose has security implications. +Therefore, this avenue is intentionally restricted and only supports `ZSTD_CLEVEL`. + +### Long distance matching mode The long distance matching mode, enabled with `--long`, is designed to improve the compression ratio for files with long matches at a large distance (up to the maximum window size, `128 MiB`) while still maintaining compression speed. @@ -233,7 +236,7 @@ The below table illustrates this on the [Silesia compression corpus]. | `zstd -10 --long`| `3.566` | `16.2 MB/s` | `415.7 MB/s` | -#### zstdgrep +### zstdgrep `zstdgrep` is a utility which makes it possible to `grep` directly a `.zst` compressed file. It's used the same way as normal `grep`, for example : From 15561bcf74ce18087aaa5e24620cdc23057840e3 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Thu, 7 May 2020 13:12:59 -0400 Subject: [PATCH 351/402] Fix pkg-config File Generation Again Again Resubmission of #2001. This switches the `sed` invocations to use `-E`, extended regex syntax, which is better standardized across platforms. I guess. Same test plan: ``` make -C lib clean libzstd.pc cat lib/libzstd.pc echo # should fail make -C lib clean libzstd.pc LIBDIR=/foo make -C lib clean libzstd.pc INCLUDEDIR=/foo make -C lib clean libzstd.pc LIBDIR=/usr/localfoo make -C lib clean libzstd.pc INCLUDEDIR=/usr/localfoo make -C lib clean libzstd.pc LIBDIR=/usr/local/lib prefix=/foo make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/include prefix=/foo echo # should succeed make -C lib clean libzstd.pc LIBDIR=/usr/local/foo make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/foo make -C lib clean libzstd.pc LIBDIR=/usr/local/ make -C lib clean libzstd.pc INCLUDEDIR=/usr/local/ make -C lib clean libzstd.pc LIBDIR=/usr/local make -C lib clean libzstd.pc INCLUDEDIR=/usr/local make -C lib clean libzstd.pc LIBDIR=/tmp/foo prefix=/tmp make -C lib clean libzstd.pc INCLUDEDIR=/tmp/foo prefix=/tmp make -C lib clean libzstd.pc LIBDIR=/tmp/foo prefix=/tmp/foo make -C lib clean libzstd.pc INCLUDEDIR=/tmp/foo prefix=/tmp/foo echo # should also succeed make -C lib clean libzstd.pc prefix=/foo LIBDIR=/foo/bar INCLUDEDIR=/foo/ cat lib/libzstd.pc mkdir out cd out cmake ../build/cmake make cat lib/libzstd.pc ``` --- build/cmake/lib/CMakeLists.txt | 5 +++-- lib/Makefile | 30 ++++++++++++++++++++++++++---- lib/libzstd.pc.in | 4 ++-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index 9e758dac08c..666da60c1e8 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -137,11 +137,12 @@ endif () if (UNIX) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") - set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") + set(LIBDIR "${CMAKE_INSTALL_LIBDIR}") + set(INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") set(VERSION "${zstd_VERSION}") add_custom_target(libzstd.pc ALL ${CMAKE_COMMAND} -DIN="${LIBRARY_DIR}/libzstd.pc.in" -DOUT="libzstd.pc" - -DPREFIX="${PREFIX}" -DVERSION="${VERSION}" + -DPREFIX="${PREFIX}" -DLIBDIR="${LIBDIR}" -DINCLUDEDIR="${INCLUDEDIR}" -DVERSION="${VERSION}" -P "${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig.cmake" COMMENT "Creating pkg-config file") diff --git a/lib/Makefile b/lib/Makefile index e1c9e6c0b0a..02e2f01a0c4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -257,11 +257,31 @@ DESTDIR ?= prefix ?= /usr/local PREFIX ?= $(prefix) exec_prefix ?= $(PREFIX) -libdir ?= $(exec_prefix)/lib +EXEC_PREFIX ?= $(exec_prefix) +libdir ?= $(EXEC_PREFIX)/lib LIBDIR ?= $(libdir) includedir ?= $(PREFIX)/include INCLUDEDIR ?= $(includedir) +PCLIBDIR ?= $(shell echo "$(LIBDIR)" | sed -n -E -e "s@^$(EXEC_PREFIX)(/|$$)@@p") +PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | sed -n -E -e "s@^$(PREFIX)(/|$$)@@p") + +ifeq (,$(PCLIBDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCLIBDIR +ifeq (,$(shell echo "$(LIBDIR)" | sed -n -E -e "\\@^$(EXEC_PREFIX)(/|$$)@ p")) +$(error configured libdir ($(LIBDIR)) is outside of prefix ($(PREFIX)), can't generate pkg-config file) +endif +endif + +ifeq (,$(PCINCDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCINCDIR +ifeq (,$(shell echo "$(INCLUDEDIR)" | sed -n -E -e "\\@^$(PREFIX)(/|$$)@ p")) +$(error configured includedir ($(INCLUDEDIR)) is outside of exec_prefix ($(EXEC_PREFIX)), can't generate pkg-config file) +endif +endif + ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly)) PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig else @@ -281,9 +301,11 @@ INSTALL_DATA ?= $(INSTALL) -m 644 libzstd.pc: libzstd.pc: libzstd.pc.in @echo creating pkgconfig - $(Q)sed -e 's|@PREFIX@|$(PREFIX)|' \ - -e 's|@VERSION@|$(VERSION)|' \ - $< >$@ + $(Q)@sed -E -e 's|@PREFIX@|$(PREFIX)|' \ + -e 's|@LIBDIR@|$(PCLIBDIR)|' \ + -e 's|@INCLUDEDIR@|$(PCINCDIR)|' \ + -e 's|@VERSION@|$(VERSION)|' \ + $< >$@ install: install-pc install-static install-shared install-includes @echo zstd static and shared library installed diff --git a/lib/libzstd.pc.in b/lib/libzstd.pc.in index e7880be475d..8ec0235ad9b 100644 --- a/lib/libzstd.pc.in +++ b/lib/libzstd.pc.in @@ -4,8 +4,8 @@ prefix=@PREFIX@ exec_prefix=${prefix} -includedir=${prefix}/include -libdir=${exec_prefix}/lib +includedir=${prefix}/@INCLUDEDIR@ +libdir=${exec_prefix}/@LIBDIR@ Name: zstd Description: fast lossless compression algorithm library From 78aa9373cb41d080f8b466dd293b9b1e4fd7a683 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 8 May 2020 13:06:31 -0400 Subject: [PATCH 352/402] Add libzstd.pc Build to More Aggregate Targets in Makefiles --- Makefile | 4 ++-- lib/Makefile | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 14419feabac..2c1d34604fe 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ allmost: allzstd zlibwrapper # skip zwrapper, can't build that on alternate architectures without the proper zlib installed .PHONY: allzstd -allzstd: lib +allzstd: lib-all $(MAKE) -C $(PRGDIR) all $(MAKE) -C $(TESTDIR) all @@ -55,7 +55,7 @@ all32: $(MAKE) -C $(TESTDIR) all32 .PHONY: lib lib-release libzstd.a -lib lib-release : +lib lib-release lib-all : @$(MAKE) -C $(ZSTDDIR) $@ .PHONY: zstd zstd-release diff --git a/lib/Makefile b/lib/Makefile index 02e2f01a0c4..0a01ffc6fe6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -180,11 +180,14 @@ else endif -.PHONY: default all clean install uninstall +.PHONY: default lib-all all clean install uninstall default: lib-release -all: lib +# alias +lib-all: all + +all: lib libzstd.pc libzstd.a: ARFLAGS = rcs libzstd.a: $(ZSTD_OBJ) From 85801b99d751df6bf94882aee24119fb649fdacd Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 8 May 2020 13:10:20 -0400 Subject: [PATCH 353/402] Test libzstd.pc Build on Travis OS X --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index eae5bb63b1e..01baee399cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -184,6 +184,7 @@ matrix: os: osx script: - make test + - make -C lib all - name: zbuff test if: branch = master From 87c541c5f969b6f62159318ffd20fac5eae154f8 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 8 May 2020 16:01:26 -0400 Subject: [PATCH 354/402] Only Trigger libzstd.pc Build on Unix-Like Platforms We don't even define the rule on unsupported platforms. --- lib/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Makefile b/lib/Makefile index 0a01ffc6fe6..7c6dff02468 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -187,7 +187,7 @@ default: lib-release # alias lib-all: all -all: lib libzstd.pc +all: lib libzstd.a: ARFLAGS = rcs libzstd.a: $(ZSTD_OBJ) @@ -253,6 +253,8 @@ clean: #----------------------------------------------------------------------------- ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku)) +all: libzstd.pc + DESTDIR ?= # directory variables : GNU conventions prefer lowercase # see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html From d564d564407b341b8c7343508e17251487731642 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 8 May 2020 13:35:59 -0700 Subject: [PATCH 355/402] document additional compilation macros ZSTD_NOBENCH, ZSTD_NODICT, ZSTD_NOCOMPRESS, ZSTD_NODECOMPRESS --- programs/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/programs/README.md b/programs/README.md index 2f212f68ad1..53706de727b 100644 --- a/programs/README.md +++ b/programs/README.md @@ -61,6 +61,24 @@ There are however other Makefile targets that create different variations of CLI In which case, linking stage will fail if `lz4` library cannot be found. This is useful to prevent silent feature disabling. +- __ZSTD_NOBENCH__ : `zstd` cli will be compiled without its integrated benchmark module. + This can be useful to produce smaller binaries. + In this case, the corresponding unit can also be excluded from compilation target. + +- __ZSTD_NODICT__ : `zstd` cli will be compiled without support for the integrated dictionary builder. + This can be useful to produce smaller binaries. + In this case, the corresponding unit can also be excluded from compilation target. + +- __ZSTD_NOCOMPRESS__ : `zstd` cli will be compiled without support for compression. + The resulting binary will only be able to decompress files. + This can be useful to produce smaller binaries. + A corresponding `Makefile` target using this ability is `zstd-decompress`. + +- __ZSTD_NODECOMPRESS__ : `zstd` cli will be compiled without support for decompression. + The resulting binary will only be able to compress files. + This can be useful to produce smaller binaries. + A corresponding `Makefile` target using this ability is `zstd-compress`. + - __BACKTRACE__ : `zstd` can display a stack backtrace when execution generates a runtime exception. By default, this feature may be degraded/disabled on some platforms unless additional compiler directives are From 376c26bf566c0dd7abc3920da861147b5f491fc7 Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Fri, 8 May 2020 16:42:15 -0400 Subject: [PATCH 356/402] Use Unused Variable --- programs/zstdcli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 81f1910c202..4a1e3193d38 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -1285,7 +1285,8 @@ int main(int const argCount, const char* argv[]) /* Compare strategies constant with the ground truth */ { ZSTD_bounds strategyBounds = ZSTD_cParam_getBounds(ZSTD_c_strategy); - assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound);} + assert(ZSTD_NB_STRATEGIES == strategyBounds.upperBound); + (void)strategyBounds; } if (showDefaultCParams) { size_t fileNb; From e5366bee16cc1a9ba53c44dbcb80de60f294700d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 8 May 2020 14:14:46 -0700 Subject: [PATCH 357/402] updated `zstd -h` to help readability. Group arguments into categories, try to give better visibility to more common arguments. --- programs/Makefile | 11 +++--- programs/zstdcli.c | 91 +++++++++++++++++++++++++++------------------- 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index 1a85f185e5c..4bf147972c6 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -213,13 +213,13 @@ zstd-noxz : LZMALD := zstd-noxz : LZMA_MSG := - xz/lzma support is disabled zstd-noxz : zstd -# note : the following target doesn't build +## zstd-dll: zstd executable linked to dynamic library libzstd (must already exist) +# note : the following target doesn't link # because zstd uses non-public symbols from libzstd # such as XXH64 (for benchmark), -# ZDICT_trainFromBuffer_unsafe_legacy for dictionary builder -# and ZSTD_cycleLog (likely for --patch-from) -# It's unclear at this stage if this is a scenario we want to support -## zstd-dll: zstd executable linked to dynamic library libzstd (must already exist) +# ZDICT_trainFromBuffer_unsafe_legacy (for dictionary builder) +# and ZSTD_cycleLog (likely for --patch-from). +# It's unclear at this stage if this is a scenario that must be supported .PHONY: zstd-dll zstd-dll : LDFLAGS+= -L$(ZSTDDIR) -lzstd zstd-dll : ZSTDLIB_FILES = @@ -227,6 +227,7 @@ zstd-dll : $(ZSTD_CLI_OBJ) $(CC) $(FLAGS) $^ -o $@$(EXT) $(LDFLAGS) +## zstd-pgo: zstd executable optimized with pgo. `gcc` only. zstd-pgo : $(MAKE) clean $(MAKE) zstd MOREFLAGS=-fprofile-generate diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 81f1910c202..b6d3e1afa47 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -122,9 +122,9 @@ static void usage(FILE* f, const char* programName) #ifndef ZSTD_NODECOMPRESS DISPLAY_F(f, " -d : decompression \n"); #endif - DISPLAY_F(f, " -D file: use `file` as Dictionary \n"); - DISPLAY_F(f, " -o file: result stored into `file` (only if 1 input file) \n"); - DISPLAY_F(f, " -f : overwrite output without prompting and (de)compress links \n"); + DISPLAY_F(f, " -D DICT: use DICT as Dictionary for compression or decompression \n"); + DISPLAY_F(f, " -o file: result stored into file \n"); + DISPLAY_F(f, " -f : overwrite output without prompting, also (de)compress links \n"); DISPLAY_F(f, "--rm : remove source file(s) after successful de/compression \n"); DISPLAY_F(f, " -k : preserve source file(s) (default) \n"); DISPLAY_F(f, " -h/-H : display help/long help and exit \n"); @@ -137,34 +137,42 @@ static void usage_advanced(const char* programName) DISPLAYOUT( "\n"); DISPLAYOUT( "Advanced arguments : \n"); DISPLAYOUT( " -V : display Version number and exit \n"); - DISPLAYOUT( " -v : verbose mode; specify multiple times to increase verbosity\n"); - DISPLAYOUT( " -q : suppress warnings; specify twice to suppress errors too\n"); - DISPLAYOUT( " -c : force write to standard output, even if it is the console\n"); - DISPLAYOUT( " -l : print information about zstd compressed files \n"); - DISPLAYOUT( "--exclude-compressed: only compress files that are not previously compressed \n"); + + DISPLAYOUT( " -c : force write to standard output, even if it is the console \n"); + + DISPLAYOUT( " -v : verbose mode; specify multiple times to increase verbosity \n"); + DISPLAYOUT( " -q : suppress warnings; specify twice to suppress errors too \n"); + DISPLAYOUT( "--no-progress : do not display the progress counter \n"); + +#ifdef UTIL_HAS_CREATEFILELIST + DISPLAYOUT( " -r : operate recursively on directories \n"); + DISPLAYOUT( "--filelist=FILE : read list of files to operate upon from FILE \n"); + DISPLAYOUT( "--output-dir-flat=DIR : all resulting files are stored into DIR \n"); +#endif + + DISPLAYOUT( "-- : All arguments after \"--\" are treated as files \n"); + #ifndef ZSTD_NOCOMPRESS - DISPLAYOUT( "--ultra : enable levels beyond %i, up to %i (requires more memory)\n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); - DISPLAYOUT( "--long[=#]: enable long distance matching with given window log (default: %u)\n", g_defaultMaxWindowLog); - DISPLAYOUT( "--fast[=#]: switch to very fast compression levels (default: %u)\n", 1); + DISPLAYOUT( "\n"); + DISPLAYOUT( "Advanced compression arguments : \n"); + DISPLAYOUT( "--ultra : enable levels beyond %i, up to %i (requires more memory) \n", ZSTDCLI_CLEVEL_MAX, ZSTD_maxCLevel()); + DISPLAYOUT( "--long[=#]: enable long distance matching with given window log (default: %u) \n", g_defaultMaxWindowLog); + DISPLAYOUT( "--fast[=#]: switch to very fast compression levels (default: %u) \n", 1); DISPLAYOUT( "--adapt : dynamically adapt compression level to I/O conditions \n"); - DISPLAYOUT( "--stream-size=# : optimize compression parameters for streaming input of given number of bytes \n"); - DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size\n"); - DISPLAYOUT( "--target-compressed-block-size=# : make compressed block near targeted size \n"); # ifdef ZSTD_MULTITHREAD DISPLAYOUT( " -T# : spawns # compression threads (default: 1, 0==# cores) \n"); DISPLAYOUT( " -B# : select size of each job (default: 0==automatic) \n"); - DISPLAYOUT( " --single-thread : use a single thread for both I/O and compression (result slightly different than -T1)\n"); + DISPLAYOUT( "--single-thread : use a single thread for both I/O and compression (result slightly different than -T1) \n"); DISPLAYOUT( "--rsyncable : compress using a rsync-friendly method (-B sets block size) \n"); # endif - DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression)\n"); - DISPLAYOUT( "--[no-]check : integrity check (default: enabled) \n"); + DISPLAYOUT( "--exclude-compressed: only compress files that are not already compressed \n"); + DISPLAYOUT( "--stream-size=# : specify size of streaming input from `stdin` \n"); + DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size \n"); + DISPLAYOUT( "--target-compressed-block-size=# : generate compressed block of approximately targeted size \n"); + DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression only) \n"); + DISPLAYOUT( "--[no-]check : add XXH64 integrity checksum to frame (default: enabled) \n"); DISPLAYOUT( "--[no-]compress-literals : force (un)compressed literals \n"); -#endif /* !ZSTD_NOCOMPRESS */ -#ifdef UTIL_HAS_CREATEFILELIST - DISPLAYOUT( " -r : operate recursively on directories \n"); - DISPLAYOUT( "--filelist=FILE : read a list of files from FILE. \n"); - DISPLAYOUT( "--output-dir-flat=DIR : all resulting files are stored into DIR. \n"); -#endif + DISPLAYOUT( "--format=zstd : compress files to the .zst format (default) \n"); #ifdef ZSTD_GZCOMPRESS DISPLAYOUT( "--format=gzip : compress files to the .gz format \n"); @@ -176,37 +184,44 @@ static void usage_advanced(const char* programName) #ifdef ZSTD_LZ4COMPRESS DISPLAYOUT( "--format=lz4 : compress files to the .lz4 format \n"); #endif +#endif /* !ZSTD_NOCOMPRESS */ + #ifndef ZSTD_NODECOMPRESS + DISPLAYOUT( "\n"); + DISPLAYOUT( "Advanced decompression arguments : \n"); + DISPLAYOUT( " -l : print information about zstd compressed files \n"); DISPLAYOUT( "--test : test compressed file integrity \n"); -#if ZSTD_SPARSE_DEFAULT - DISPLAYOUT( "--[no-]sparse : sparse mode (default: enabled on file, disabled on stdout)\n"); -#else - DISPLAYOUT( "--[no-]sparse : sparse mode (default: disabled)\n"); -#endif -#endif DISPLAYOUT( " -M# : Set a memory usage limit for decompression \n"); - DISPLAYOUT( "--no-progress : do not display the progress bar \n"); - DISPLAYOUT( "-- : All arguments after \"--\" are treated as files \n"); +# if ZSTD_SPARSE_DEFAULT + DISPLAYOUT( "--[no-]sparse : sparse mode (default: enabled on file, disabled on stdout) \n"); +# else + DISPLAYOUT( "--[no-]sparse : sparse mode (default: disabled) \n"); +# endif +#endif /* ZSTD_NODECOMPRESS */ + #ifndef ZSTD_NODICT DISPLAYOUT( "\n"); DISPLAYOUT( "Dictionary builder : \n"); DISPLAYOUT( "--train ## : create a dictionary from a training set of files \n"); - DISPLAYOUT( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args\n"); - DISPLAYOUT( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args\n"); - DISPLAYOUT( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u)\n", g_defaultSelectivityLevel); - DISPLAYOUT( " -o file : `file` is dictionary name (default: %s) \n", g_defaultDictName); + DISPLAYOUT( "--train-cover[=k=#,d=#,steps=#,split=#,shrink[=#]] : use the cover algorithm with optional args \n"); + DISPLAYOUT( "--train-fastcover[=k=#,d=#,f=#,steps=#,split=#,accel=#,shrink[=#]] : use the fast cover algorithm with optional args \n"); + DISPLAYOUT( "--train-legacy[=s=#] : use the legacy algorithm with selectivity (default: %u) \n", g_defaultSelectivityLevel); + DISPLAYOUT( " -o DICT : DICT is dictionary name (default: %s) \n", g_defaultDictName); DISPLAYOUT( "--maxdict=# : limit dictionary to specified size (default: %u) \n", g_defaultMaxDictSize); - DISPLAYOUT( "--dictID=# : force dictionary ID to specified value (default: random)\n"); + DISPLAYOUT( "--dictID=# : force dictionary ID to specified value (default: random) \n"); #endif + #ifndef ZSTD_NOBENCH DISPLAYOUT( "\n"); DISPLAYOUT( "Benchmark arguments : \n"); DISPLAYOUT( " -b# : benchmark file(s), using # compression level (default: %d) \n", ZSTDCLI_CLEVEL_DEFAULT); - DISPLAYOUT( " -e# : test all compression levels from -bX to # (default: 1)\n"); + DISPLAYOUT( " -e# : test all compression levels successively from -b# to -e# (default: 1) \n"); DISPLAYOUT( " -i# : minimum evaluation time in seconds (default: 3s) \n"); - DISPLAYOUT( " -B# : cut file into independent blocks of size # (default: no block)\n"); + DISPLAYOUT( " -B# : cut file into independent blocks of size # (default: no block) \n"); + DISPLAYOUT( " -S : output one benchmark result per input file (default: consolidated result) \n"); DISPLAYOUT( "--priority=rt : set process priority to real-time \n"); #endif + } static void badusage(const char* programName) From 37b2dafbed966d323f8a519a327aa3267fcad4c0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 8 May 2020 14:20:47 -0700 Subject: [PATCH 358/402] minor clarification on `-o file` --- programs/zstdcli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index b6d3e1afa47..45b5bd0c8ea 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -123,7 +123,7 @@ static void usage(FILE* f, const char* programName) DISPLAY_F(f, " -d : decompression \n"); #endif DISPLAY_F(f, " -D DICT: use DICT as Dictionary for compression or decompression \n"); - DISPLAY_F(f, " -o file: result stored into file \n"); + DISPLAY_F(f, " -o file: result stored into `file` (only 1 output file) \n"); DISPLAY_F(f, " -f : overwrite output without prompting, also (de)compress links \n"); DISPLAY_F(f, "--rm : remove source file(s) after successful de/compression \n"); DISPLAY_F(f, " -k : preserve source file(s) (default) \n"); From dd026ca505fee886ccfd5d1c453ebe42d78f84fc Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 9 May 2020 11:30:45 -0700 Subject: [PATCH 359/402] re-inforced tests for initStaticCCtx ensure that `estimateCCtxSize()` works as intended. --- tests/fuzzer.c | 83 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index c9cf85bdbe4..1983ae1421d 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1066,11 +1066,12 @@ static int basicUnitTests(U32 const seed, double compressibility) /* Static CCtx tests */ #define STATIC_CCTX_LEVEL 3 - DISPLAYLEVEL(3, "test%3i : create static CCtx for level %u :", testNb++, STATIC_CCTX_LEVEL); - { size_t const staticCCtxSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL); - void* const staticCCtxBuffer = malloc(staticCCtxSize); + DISPLAYLEVEL(3, "test%3i : create static CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL); + { size_t const staticCStreamSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL); + void* const staticCCtxBuffer = malloc(staticCStreamSize); size_t const staticDCtxSize = ZSTD_estimateDCtxSize(); void* const staticDCtxBuffer = malloc(staticDCtxSize); + DISPLAYLEVEL(4, "CStream size = %u, ", (U32)staticCStreamSize); if (staticCCtxBuffer==NULL || staticDCtxBuffer==NULL) { free(staticCCtxBuffer); free(staticDCtxBuffer); @@ -1078,17 +1079,25 @@ static int basicUnitTests(U32 const seed, double compressibility) testResult = 1; goto _end; } - { ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize); - ZSTD_DCtx* staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); + { size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL); + ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize); + ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; + DISPLAYLEVEL(4, "CCtx size = %u, ", (U32)staticCCtxSize); DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : compress immediately with static CCtx : ", testNb++); + CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, + compressedBuffer, compressedBufferSize, + CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", + (unsigned)cSize, (double)cSize/CNBuffSize*100); + DISPLAYLEVEL(3, "test%3i : init CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL); - { size_t const r = ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL); - if (ZSTD_isError(r)) goto _output_error; } + CHECK_Z( ZSTD_compressBegin(staticCCtx, STATIC_CCTX_LEVEL) ); DISPLAYLEVEL(3, "OK \n"); - DISPLAYLEVEL(3, "test%3i : simple compression test with static CCtx : ", testNb++); + DISPLAYLEVEL(3, "test%3i : compression again with static CCtx : ", testNb++); CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); @@ -1103,11 +1112,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++); - { size_t u; - for (u=0; u Date: Sun, 10 May 2020 16:36:08 +0800 Subject: [PATCH 360/402] programs/Makefile: make it actually work with clang Recent versions of clang seem to require a step of conversion from the profraw file to a "compiler-readable" profdata file to let PGO work. --- programs/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/Makefile b/programs/Makefile index 1a85f185e5c..8ef53a01755 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -237,6 +237,7 @@ zstd-pgo : ./zstd -b7i2 $(PROFILE_WITH) ./zstd -b5 $(PROFILE_WITH) $(RM) zstd *.o $(ZSTDDECOMP_O) $(ZSTDDIR)/compress/*.o + case $(CC) in *clang*) if ! [ -e default.profdata ]; then llvm-profdata merge -output=default.profdata default*.profraw; fi ;; esac $(MAKE) zstd MOREFLAGS=-fprofile-use ## zstd-small: minimal target, supporting only zstd compression and decompression. no bench. no legacy. no other format. @@ -277,7 +278,7 @@ clean: @$(RM) core *.o tmp* result* *.gcda dictionary *.zst \ zstd$(EXT) zstd32$(EXT) zstd-compress$(EXT) zstd-decompress$(EXT) \ zstd-small$(EXT) zstd-frugal$(EXT) zstd-nolegacy$(EXT) zstd4$(EXT) \ - zstd-dictBuilder$(EXT) *.gcda default.profraw have_zlib$(EXT) + zstd-dictBuilder$(EXT) *.gcda default*.profraw default.profdata have_zlib$(EXT) @echo Cleaning completed MD2ROFF = ronn From ef467fd428a26f93d498ef6c3cfb6aa57f9f49c9 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 11 May 2020 12:22:45 -0500 Subject: [PATCH 361/402] documenting non-supported grep options for zstdgrep --- programs/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/programs/README.md b/programs/README.md index 53706de727b..63ce79fc18f 100644 --- a/programs/README.md +++ b/programs/README.md @@ -272,6 +272,19 @@ It's used the same way as normal `grep`, for example : `zstdgrep pattern file.zst` `zstdgrep` is _not_ compatible with dictionary compression. +`zstdgrep` does not support the following grep options + +``` +--dereference-recursive (-R) + --directories (-d) + --exclude + --exclude-from + --exclude-dir + --include + --null (-Z), + --null-data (-z) + --recursive (-r) +``` To search into a file compressed with a dictionary, it's necessary to decompress it using `zstd` or `zstdcat`, From f2f86b50ae345ac29c860d98d73e8454ec517a4a Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 11 May 2020 12:29:03 -0700 Subject: [PATCH 362/402] Update benchmarks and add fast mode --- README.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cb956690db1..5c300fdc49a 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ a list of known ports and bindings is provided on [Zstandard homepage](http://ww ## Benchmarks For reference, several fast compression algorithms were tested and compared -on a server running Arch Linux (`Linux version 5.0.5-arch1-1`), +on a server running Arch Linux (`Linux version 5.5.11-arch1-1`), with a Core i9-9900K CPU @ 5.0GHz, using [lzbench], an open-source in-memory benchmark by @inikep -compiled with [gcc] 8.2.1, +compiled with [gcc] 9.3.0, on the [Silesia compression corpus]. [lzbench]: https://github.com/inikep/lzbench @@ -43,18 +43,26 @@ on the [Silesia compression corpus]. | Compressor name | Ratio | Compression| Decompress.| | --------------- | ------| -----------| ---------- | -| **zstd 1.4.4 -1** | 2.884 | 520 MB/s | 1600 MB/s | -| zlib 1.2.11 -1 | 2.743 | 110 MB/s | 440 MB/s | -| brotli 1.0.7 -0 | 2.701 | 430 MB/s | 470 MB/s | -| quicklz 1.5.0 -1 | 2.238 | 600 MB/s | 800 MB/s | -| lzo1x 2.09 -1 | 2.106 | 680 MB/s | 950 MB/s | -| lz4 1.8.3 | 2.101 | 800 MB/s | 4220 MB/s | -| snappy 1.1.4 | 2.073 | 580 MB/s | 2020 MB/s | -| lzf 3.6 -1 | 2.077 | 440 MB/s | 930 MB/s | +| **zstd 1.4.5 -1** | 2.884 | 500 MB/s | 1660 MB/s | +| zlib 1.2.11 -1 | 2.743 | 90 MB/s | 400 MB/s | +| brotli 1.0.7 -0 | 2.703 | 400 MB/s | 450 MB/s | +| **zstd 1.4.5 --fast=1** | 2.434 | 570 MB/s | 2200 MB/s | +| **zstd 1.4.5 --fast=3** | 2.312 | 640 MB/s | 2300 MB/s | +| quicklz 1.5.0 -1 | 2.238 | 560 MB/s | 710 MB/s | +| **zstd 1.4.5 --fast=5** | 2.178 | 700 MB/s | 2420 MB/s | +| lzo1x 2.10 -1 | 2.106 | 690 MB/s | 820 MB/s | +| lz4 1.9.2 | 2.101 | 740 MB/s | 4530 MB/s | +| **zstd 1.4.5 --fast=7** | 2.096 | 750 MB/s | 2480 MB/s | +| lzf 3.6 -1 | 2.077 | 410 MB/s | 860 MB/s | +| snappy 1.1.8 | 2.073 | 560 MB/s | 1790 MB/s | [zlib]: http://www.zlib.net/ [LZ4]: http://www.lz4.org/ +The negative compression levels, specified with `--fast=#`, +offer faster compression and decompression speed in exchange for some loss in +compression ratio compared to level 1, as seen in the table above. + Zstd can also offer stronger compression ratios at the cost of compression speed. Speed vs Compression trade-off is configurable by small increments. Decompression speed is preserved and remains roughly the same at all settings, From c6636afbbb0d545347b17565b007195efaa3764e Mon Sep 17 00:00:00 2001 From: "W. Felix Handte" Date: Mon, 11 May 2020 18:53:32 -0400 Subject: [PATCH 363/402] Fix ZSTD_estimateCCtxSize() Under ASAN `ZSTD_estimateCCtxSize()` provides estimates for one-shot compression, which is guaranteed not to buffer inputs or outputs. So it ignores the sizes of the buffers, assuming they'll be zero. However, the actual workspace allocation logic always allocates those buffers, and when running under ASAN, the workspace surrounds every allocation with 256 bytes of redzone. So the 0-sized buffers end up consuming 512 bytes of space, which is accounted for in the actual allocation path through the use of `ZSTD_cwksp_alloc_size()` but isn't in the estimation path, since it ignores the buffers entirely. This commit fixes this. --- lib/compress/zstd_compress.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ff8a00e6b3b..538f8e9e2ab 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -1144,13 +1144,26 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq)); - size_t const neededSpace = entropySpace + blockStateSpace + tokenSpace + - matchStateSize + ldmSpace + ldmSeqSpace; + /* estimateCCtxSize is for one-shot compression. So no buffers should + * be needed. However, we still allocate two 0-sized buffers, which can + * take space under ASAN. */ + size_t const bufferSpace = ZSTD_cwksp_alloc_size(0) + + ZSTD_cwksp_alloc_size(0); + size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)); - DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)cctxSpace); + size_t const neededSpace = + cctxSpace + + entropySpace + + blockStateSpace + + ldmSpace + + ldmSeqSpace + + matchStateSize + + tokenSpace + + bufferSpace; + DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); - return cctxSpace + neededSpace; + return neededSpace; } } From 608f1bfc4cf4eb92470cb8c31373effd511d0db9 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 11 May 2020 18:16:38 -0700 Subject: [PATCH 364/402] fixed context downsize with initStatic When context is created using initStatic, no resize is possible. fix : only bump oversizeDuration when !initStatic --- lib/compress/zstd_compress.c | 21 +++++++++------------ tests/fuzzer.c | 22 ++++++++++++++++++---- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 538f8e9e2ab..8776c5cd270 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -15,7 +15,7 @@ #include /* memset */ #include "../common/cpu.h" #include "../common/mem.h" -#include "hist.h" /* HIST_countFast_wksp */ +#include "hist.h" /* HIST_countFast_wksp */ #define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ #include "../common/fse.h" #define HUF_STATIC_LINKING_ONLY @@ -90,7 +90,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) } } -ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize) +ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) { ZSTD_cwksp ws; ZSTD_CCtx* cctx; @@ -99,9 +99,8 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize) ZSTD_cwksp_init(&ws, workspace, workspaceSize); cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx)); - if (cctx == NULL) { - return NULL; - } + if (cctx == NULL) return NULL; + memset(cctx, 0, sizeof(ZSTD_CCtx)); ZSTD_cwksp_move(&cctx->workspace, &ws); cctx->staticSize = workspaceSize; @@ -110,8 +109,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize) if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object( - &cctx->workspace, HUF_WORKSPACE_SIZE); + cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE); cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; } @@ -421,9 +419,8 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) return bounds; default: - { ZSTD_bounds const boundError = { ERROR(parameter_unsupported), 0, 0 }; - return boundError; - } + bounds.error = ERROR(parameter_unsupported); + return bounds; } } @@ -1458,7 +1455,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, needsIndexReset = ZSTDirp_reset; } - ZSTD_cwksp_bump_oversized_duration(ws, 0); + if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); /* Check if workspace is large enough, alloc a new one if needed */ { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; @@ -1774,7 +1771,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, ZSTD_buffered_policy_e zbuff) { DEBUGLOG(5, "ZSTD_copyCCtx_internal"); - RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, + RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, "Can't copy a ctx that's not in init stage."); memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 1983ae1421d..4efaf519aef 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -32,6 +32,7 @@ #include "fse.h" #include "zstd.h" /* ZSTD_VERSION_STRING */ #include "zstd_errors.h" /* ZSTD_getErrorCode */ +#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION */ #include "zstdmt_compress.h" #define ZDICT_STATIC_LINKING_ONLY #include "zdict.h" /* ZDICT_trainFromBuffer */ @@ -1065,7 +1066,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "OK \n"); /* Static CCtx tests */ -#define STATIC_CCTX_LEVEL 3 +#define STATIC_CCTX_LEVEL 4 DISPLAYLEVEL(3, "test%3i : create static CCtx for level %u : ", testNb++, STATIC_CCTX_LEVEL); { size_t const staticCStreamSize = ZSTD_estimateCStreamSize(STATIC_CCTX_LEVEL); void* const staticCCtxBuffer = malloc(staticCStreamSize); @@ -1079,19 +1080,31 @@ static int basicUnitTests(U32 const seed, double compressibility) testResult = 1; goto _end; } - { size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL); + { size_t const smallInSize = 32 KB; + size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL); ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize); ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); - if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; DISPLAYLEVEL(4, "CCtx size = %u, ", (U32)staticCCtxSize); + if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; DISPLAYLEVEL(3, "OK \n"); - + /* DISPLAYLEVEL(3, "test%3i : compress immediately with static CCtx : ", testNb++); CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); + */ + DISPLAYLEVEL(3, "test%3i : compress small input often enough to trigger context reduce : ", testNb++); + { int nbc; + assert(CNBuffSize > smallInSize + ZSTD_WORKSPACETOOLARGE_MAXDURATION + 3); + for (nbc=0; nbc Date: Mon, 11 May 2020 18:50:10 -0700 Subject: [PATCH 365/402] updated initStatic tests differentiate small CCtx for small inputs from full CCtx from CStream contexts. Ensure allocation & resize tests are more precise. --- tests/fuzzer.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4efaf519aef..0202b331827 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -32,7 +32,7 @@ #include "fse.h" #include "zstd.h" /* ZSTD_VERSION_STRING */ #include "zstd_errors.h" /* ZSTD_getErrorCode */ -#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION */ +#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ #include "zstdmt_compress.h" #define ZDICT_STATIC_LINKING_ONLY #include "zdict.h" /* ZDICT_trainFromBuffer */ @@ -47,8 +47,6 @@ /*-************************************ * Constants **************************************/ -#define KB *(1U<<10) -#define MB *(1U<<20) #define GB *(1U<<30) static const int FUZ_compressibility_default = 50; @@ -1081,20 +1079,44 @@ static int basicUnitTests(U32 const seed, double compressibility) goto _end; } { size_t const smallInSize = 32 KB; + ZSTD_compressionParameters const cparams_small = ZSTD_getCParams(STATIC_CCTX_LEVEL, smallInSize, 0); + size_t const smallCCtxSize = ZSTD_estimateCCtxSize_usingCParams(cparams_small); size_t const staticCCtxSize = ZSTD_estimateCCtxSize(STATIC_CCTX_LEVEL); - ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, staticCCtxSize); + ZSTD_CCtx* staticCCtx = ZSTD_initStaticCCtx(staticCCtxBuffer, smallCCtxSize); ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); - DISPLAYLEVEL(4, "CCtx size = %u, ", (U32)staticCCtxSize); + DISPLAYLEVEL(4, "Full CCtx size = %u, ", (U32)staticCCtxSize); + DISPLAYLEVEL(4, "CCtx for 32 KB = %u, ", (U32)smallCCtxSize); + assert(staticCCtxSize > smallCCtxSize * ZSTD_WORKSPACETOOLARGE_FACTOR); /* ensure size down scenario */ if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; DISPLAYLEVEL(3, "OK \n"); - /* - DISPLAYLEVEL(3, "test%3i : compress immediately with static CCtx : ", testNb++); + + DISPLAYLEVEL(3, "test%3i : compress small input with small static CCtx : ", testNb++); + CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, + compressedBuffer, compressedBufferSize, + CNBuffer, smallInSize, STATIC_CCTX_LEVEL) ); + DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", + (unsigned)cSize, (double)cSize/smallInSize*100); + + DISPLAYLEVEL(3, "test%3i : compress large input with small static CCtx (must fail) : ", testNb++); + { size_t const r = ZSTD_compressCCtx(staticCCtx, + compressedBuffer, compressedBufferSize, + CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL); + if (ZSTD_getErrorCode((size_t)r) != ZSTD_error_memory_allocation) goto _output_error; + } + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : resize context to full CCtx size : ", testNb++); + staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCCtxSize); + if ((void*)staticCCtx != staticCCtxBuffer) goto _output_error; + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : compress large input with static CCtx : ", testNb++); CHECK_VAR(cSize, ZSTD_compressCCtx(staticCCtx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize, STATIC_CCTX_LEVEL) ); DISPLAYLEVEL(3, "OK (%u bytes : %.2f%%)\n", (unsigned)cSize, (double)cSize/CNBuffSize*100); - */ + DISPLAYLEVEL(3, "test%3i : compress small input often enough to trigger context reduce : ", testNb++); { int nbc; assert(CNBuffSize > smallInSize + ZSTD_WORKSPACETOOLARGE_MAXDURATION + 3); @@ -1148,6 +1170,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : resize context to CStream size, then stream compress : ", testNb++); staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCStreamSize); + assert(staticCCtx != NULL); CHECK_Z( ZSTD_initCStream(staticCCtx, STATIC_CCTX_LEVEL) ); /* note : doesn't allocate */ { ZSTD_outBuffer output = { compressedBuffer, compressedBufferSize, 0 }; ZSTD_inBuffer input = { CNBuffer, CNBuffSize, 0 }; From e7d2391e9a75154657183b049b69a7a2effa9724 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Mon, 11 May 2020 20:55:01 -0500 Subject: [PATCH 366/402] [doc] measuring performance docs (#2117) * performance measuring docs * spelling * combining advanced and simple section * zstd benchmark title change --- CONTRIBUTING.md | 204 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23d62c099ce..637e3718855 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,7 +44,7 @@ Our contribution process works in three main stages: git pull https://github.com/facebook/zstd dev git push origin dev ``` - * Topic and deveopment: + * Topic and development: * Make a new branch on your fork about the topic you're developing for ``` # branch names should be consise but sufficiently informative @@ -80,7 +80,7 @@ Our contribution process works in three main stages: as the destination. * Examine the diff presented between the two branches to make sure there is nothing unexpected. * Write a good pull request description: - * While there is no strict template that our contributers follow, we would like them to + * While there is no strict template that our contributors follow, we would like them to sufficiently summarize and motivate the changes they are proposing. We recommend all pull requests, at least indirectly, address the following points. * Is this pull request important and why? @@ -126,6 +126,206 @@ just `contrib/largeNbDicts` and nothing else, you can run: scan-build make -C contrib/largeNbDicts largeNbDicts ``` +## Performance +Performance is extremely important for zstd and we only merge pull requests whose performance +landscape and corresponding trade-offs have been adequately analyzed, reproduced, and presented. +This high bar for performance means that every PR which has the potential to +impact performance takes a very long time for us to properly review. That being said, we +always welcome contributions to improve performance (or worsen performance for the trade-off of +something else). Please keep the following in mind before submitting a performance related PR: + +1. Zstd isn't as old as gzip but it has been around for time now and its evolution is +very well documented via past Github issues and pull requests. It may be the case that your +particular performance optimization has already been considered in the past. Please take some +time to search through old issues and pull requests using keywords specific to your +would-be PR. Of course, just because a topic has already been discussed (and perhaps rejected +on some grounds) in the past, doesn't mean it isn't worth bringing up again. But even in that case, +it will be helpful for you to have context from that topic's history before contributing. +2. The distinction between noise and actual performance gains can unfortunately be very subtle +especially when microbenchmarking extremely small wins or losses. The only remedy to getting +something subtle merged is extensive benchmarking. You will be doing us a great favor if you +take the time to run extensive, long-duration, and potentially cross-(os, platform, process, etc) +benchmarks on your end before submitting a PR. Of course, you will not be able to benchmark +your changes on every single processor and os out there (and neither will we) but do that best +you can:) We've adding some things to think about when benchmarking below in the Benchmarking +Performance section which might be helpful for you. +3. Optimizing performance for a certain OS, processor vendor, compiler, or network system is a perfectly +legitimate thing to do as long as it does not harm the overall performance health of Zstd. +This is a hard balance to strike but please keep in mind other aspects of Zstd when +submitting changes that are clang-specific, windows-specific, etc. + +## Benchmarking Performance +Performance microbenchmarking is a tricky subject but also essential for Zstd. We value empirical +testing over theoretical speculation. This guide it not perfect but for most scenarios, it +is a good place to start. + +### Stability +Unfortunately, the most important aspect in being able to benchmark reliably is to have a stable +benchmarking machine. A virtual machine, a machine with shared resources, or your laptop +will typically not be stable enough to obtain reliable benchmark results. If you can get your +hands on a desktop, this is usually a better scenario. + +Of course, benchmarking can be done on non-hyper-stable machines as well. You will just have to +do a little more work to ensure that you are in fact measuring the changes you've made not and +noise. Here are some things you can do to make your benchmarks more stable: + +1. The most simple thing you can do to drastically improve the stability of your benchmark is +to run it multiple times and then aggregate the results of those runs. As a general rule of +thumb, the smaller the change you are trying to measure, the more samples of benchmark runs +you will have to aggregate over to get reliable results. Here are some additional things to keep in +mind when running multiple trials: + * How you aggregate your samples are important. You might be tempted to use the mean of your + results. While this is certainly going to be a more stable number than a raw single sample + benchmark number, you might have more luck by taking the median. The mean is not robust to + outliers whereas the median is. Better still, you could simply take the fastest speed your + benchmark achieved on each run since that is likely the fastest your process will be + capable of running your code. In our experience, this (aggregating by just taking the sample + with the fastest running time) has been the most stable approach. + * The more samples you have, the more stable your benchmarks should be. You can verify + your improved stability by looking at the size of your confidence intervals as you + increase your sample count. These should get smaller and smaller. Eventually hopefully + smaller than the performance win you are expecting. + * Most processors will take some time to get `hot` when running anything. The observations + you collect during that time period will very different from the true performance number. Having + a very large number of sample will help alleviate this problem slightly but you can also + address is directly by simply not including the first `n` iterations of your benchmark in + your aggregations. You can determine `n` by simply looking at the results from each iteration + and then hand picking a good threshold after which the variance in results seems to stabilize. +2. You cannot really get reliable benchmarks if your host machine is simultaneously running +another cpu/memory-intensive application in the background. If you are running benchmarks on your +personal laptop for instance, you should close all applications (including your code editor and +browser) before running your benchmarks. You might also have invisible background applications +running. You can see what these are by looking at either Activity Monitor on Mac or Task Manager +on Windows. You will get more stable benchmark results of you end those processes as well. + * If you have multiple cores, you can even run your benchmark on a reserved core to prevent + pollution from other OS and user processes. There are a number of ways to do this depending + on your OS: + * On linux boxes, you have use https://github.com/lpechacek/cpuset. + * On Windows, you can "Set Processor Affinity" using https://www.thewindowsclub.com/processor-affinity-windows + * On Mac, you can try to use their dedicated affinity API https://developer.apple.com/library/archive/releasenotes/Performance/RN-AffinityAPI/#//apple_ref/doc/uid/TP40006635-CH1-DontLinkElementID_2 +3. To benchmark, you will likely end up writing a separate c/c++ program that will link libzstd. +Dynamically linking your library will introduce some added variation (not a large amount but +definitely some). Statically linking libzstd will be more stable. Static libraries should +be enabled by default when building zstd. +4. Use a profiler with a good high resolution timer. See the section below on profiling for +details on this. +5. Disable frequency scaling, turbo boost and address space randomization (this will vary by OS) +6. Try to avoid storage. On some systems you can use tmpfs. Putting the program, inputs and outputs on +tmpfs avoids touching a real storage system, which can have a pretty big variability. + +Also check our LLVM's guide on benchmarking here: https://llvm.org/docs/Benchmarking.html + +### Zstd benchmark +The fastest signal you can get regarding your performance changes is via the in-build zstd cli +bench option. You can run Zstd as you typically would for your scenario using some set of options +and then additionally also specify the `-b#` option. Doing this will run our benchmarking pipeline +for that options you have just provided. If you want to look at the internals of how this +benchmarking script works, you can check out programs/benchzstd.c + +For example: say you have made a change that you believe improves the speed of zstd level 1. The +very first thing you should use to asses whether you actually achieved any sort of improvement +is `zstd -b`. You might try to do something like this. Note: you can use the `-i` option to +specify a running time for your benchmark in seconds (default is 3 seconds). +Usually, the longer the running time, the more stable your results will be. + +``` +$ git checkout +$ make && cp zstd zstd-old +$ git checkout +$ make && cp zstd zstd-new +$ zstd-old -i5 -b1 + 1 : 8990 -> 3992 (2.252), 302.6 MB/s , 626.4 MB/s +$ zstd-new -i5 -b1 + 1 : 8990 -> 3992 (2.252), 302.8 MB/s , 628.4 MB/s +``` + +Unless your performance win is large enough to be visible despite the intrinsic noise +on your computer, benchzstd alone will likely not be enough to validate the impact of your +changes. For example, the results of the example above indicate that effectively nothing +changed but there could be a small <3% improvement that the noise on the host machine +obscured. So unless you see a large performance win (10-15% consistently) using just +this method of evaluation will not be sufficient. + +### Profiling +There are a number of great profilers out there. We're going to briefly mention how you can +profile your code using `instruments` on mac, `perf` on linux and `visual studio profiler` +on windows. + +Say you have an idea for a change that you think will provide some good performance gains +for level 1 compression on Zstd. Typically this means, you have identified a section of +code that you think can be made to run faster. + +The first thing you will want to do is make sure that the piece of code is actually taking up +a notable amount of time to run. It is usually not worth optimzing something which accounts for less than +0.0001% of the total running time. Luckily, there are tools to help with this. +Profilers will let you see how much time your code spends inside a particular function. +If your target code snippit is only part of a function, it might be worth trying to +isolate that snippit by moving it to its own function (this is usually not necessary but +might be). + +Most profilers (including the profilers dicusssed below) will generate a call graph of +functions for you. Your goal will be to find your function of interest in this call grapch +and then inspect the time spent inside of it. You might also want to to look at the +annotated assembly which most profilers will provide you with. + +#### Instruments +We will once again consider the scenario where you think you've identified a piece of code +whose performance can be improved upon. Follow these steps to profile your code using +Instruments. + +1. Open Instruments +2. Select `Time Profiler` from the list of standard templates +3. Close all other applications except for your instruments window and your terminal +4. Run your benchmarking script from your terminal window + * You will want a benchmark that runs for at least a few seconds (5 seconds will + usually be long enough). This way the profiler will have something to work with + and you will have ample time to attach your profiler to this process:) + * I will just use benchzstd as my bencharmking script for this example: +``` +$ zstd -b1 -i5 # this will run for 5 seconds +``` +5. Once you run your benchmarking script, switch back over to instruments and attach your +process to the time profiler. You can do this by: + * Clicking on the `All Processes` drop down in the top left of the toolbar. + * Selecting your process from the dropdown. In my case, it is just going to be labled + `zstd` + * Hitting the bright red record circle button on the top left of the toolbar +6. You profiler will now start collecting metrics from your bencharking script. Once +you think you have collected enough samples (usually this is the case after 3 seconds of +recording), stop your profiler. +7. Make sure that in toolbar of the bottom window, `profile` is selected. +8. You should be able to see your call graph. + * If you don't see the call graph or an incomplete call graph, make sure you have compiled + zstd and your benchmarking scripg using debug flags. On mac and linux, this just means + you will have to supply the `-g` flag alone with your build script. You might also + have to provide the `-fno-omit-frame-pointer` flag +9. Dig down the graph to find your function call and then inspect it by double clicking +the list item. You will be able to see the annotated source code and the assembly side by +side. + +#### Perf + +This wiki has a pretty detailed tutorial on getting started working with perf so we'll +leave you to check that out of you're getting started: + +https://perf.wiki.kernel.org/index.php/Tutorial + +Some general notes on perf: +* Use `perf stat -r # ` to quickly get some relevant timing and +counter statistics. Perf uses a high resolution timer and this is likely one +of the first things your team will run when assessing your PR. +* Perf has a long list of hardware counters that can be viewed with `perf --list`. +When measuring optimizations, something worth trying is to make sure the handware +counters you expect to be impacted by your change are in fact being so. For example, +if you expect the L1 cache misses to decrease with your change, you can look at the +counter `L1-dcache-load-misses` +* Perf hardware counters will not work on a virtual machine. + +#### Visual Studio + +TODO + + ## Setting up continuous integration (CI) on your fork Zstd uses a number of different continuous integration (CI) tools to ensure that new changes are well tested before they make it to an official release. Specifically, we use the platforms From 301a62fe087ead04d4d34b1188fadcabe96d4d9f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 11 May 2020 19:00:52 -0700 Subject: [PATCH 367/402] [fuzz] Fix compress bound for dictionary_round_trip --- tests/fuzz/dictionary_round_trip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzz/dictionary_round_trip.c b/tests/fuzz/dictionary_round_trip.c index cd38178d6ae..7b7771e48e2 100644 --- a/tests/fuzz/dictionary_round_trip.c +++ b/tests/fuzz/dictionary_round_trip.c @@ -85,7 +85,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) size_t const rBufSize = size; void* rBuf = FUZZ_malloc(rBufSize); - size_t cBufSize = ZSTD_compressBound(size) * 2; + size_t cBufSize = ZSTD_compressBound(size); void *cBuf; /* Half of the time fuzz with a 1 byte smaller output size. * This will still succeed because we force the checksum to be disabled, From 1185dfb8d112da0ae2b031137c14e0d21dec8b1f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 11 May 2020 19:03:33 -0700 Subject: [PATCH 368/402] [fuzz] Add raw dictionary content fuzzer --- tests/fuzz/Makefile | 120 ++++++++++++++++++------- tests/fuzz/fuzz.py | 1 + tests/fuzz/raw_dictionary_round_trip.c | 115 ++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 30 deletions(-) create mode 100644 tests/fuzz/raw_dictionary_round_trip.c diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 571ab553bd7..3c7dc09e22f 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -41,8 +41,10 @@ FUZZ_LDFLAGS := -pthread $(LDFLAGS) FUZZ_ARFLAGS := $(ARFLAGS) FUZZ_TARGET_FLAGS = $(FUZZ_CPPFLAGS) $(FUZZ_CXXFLAGS) $(FUZZ_LDFLAGS) +FUZZ_ROUND_TRIP_FLAGS := -DFUZZING_ASSERT_VALID_SEQUENCE + FUZZ_HEADERS := fuzz_helpers.h fuzz.h zstd_helpers.h fuzz_data_producer.h -FUZZ_SRC := $(PRGDIR)/util.c fuzz_helpers.c zstd_helpers.c fuzz_data_producer.c +FUZZ_SRC := $(PRGDIR)/util.c ./fuzz_helpers.c ./zstd_helpers.c ./fuzz_data_producer.c ZSTDCOMMON_SRC := $(ZSTDDIR)/common/*.c ZSTDCOMP_SRC := $(ZSTDDIR)/compress/*.c @@ -56,9 +58,25 @@ FUZZ_SRC := \ $(ZSTDCOMP_SRC) \ $(ZSTDDICT_SRC) \ $(ZSTDLEGACY_SRC) - -FUZZ_OBJ := $(patsubst %.c,%.o, $(wildcard $(FUZZ_SRC))) - +FUZZ_SRC := $(wildcard $(FUZZ_SRC)) + +FUZZ_D_OBJ1 := $(subst $(ZSTDDIR)/common/,d_lib_common_,$(FUZZ_SRC)) +FUZZ_D_OBJ2 := $(subst $(ZSTDDIR)/compress/,d_lib_compress_,$(FUZZ_D_OBJ1)) +FUZZ_D_OBJ3 := $(subst $(ZSTDDIR)/decompress/,d_lib_decompress_,$(FUZZ_D_OBJ2)) +FUZZ_D_OBJ4 := $(subst $(ZSTDDIR)/dictBuilder/,d_lib_dictBuilder_,$(FUZZ_D_OBJ3)) +FUZZ_D_OBJ5 := $(subst $(ZSTDDIR)/legacy/,d_lib_legacy_,$(FUZZ_D_OBJ4)) +FUZZ_D_OBJ6 := $(subst $(PRGDIR)/,d_prg_,$(FUZZ_D_OBJ5)) +FUZZ_D_OBJ7 := $(subst $\./,d_fuzz_,$(FUZZ_D_OBJ6)) +FUZZ_DECOMPRESS_OBJ := $(FUZZ_D_OBJ7:.c=.o) + +FUZZ_RT_OBJ1 := $(subst $(ZSTDDIR)/common/,rt_lib_common_,$(FUZZ_SRC)) +FUZZ_RT_OBJ2 := $(subst $(ZSTDDIR)/compress/,rt_lib_compress_,$(FUZZ_RT_OBJ1)) +FUZZ_RT_OBJ3 := $(subst $(ZSTDDIR)/decompress/,rt_lib_decompress_,$(FUZZ_RT_OBJ2)) +FUZZ_RT_OBJ4 := $(subst $(ZSTDDIR)/dictBuilder/,rt_lib_dictBuilder_,$(FUZZ_RT_OBJ3)) +FUZZ_RT_OBJ5 := $(subst $(ZSTDDIR)/legacy/,rt_lib_legacy_,$(FUZZ_RT_OBJ4)) +FUZZ_RT_OBJ6 := $(subst $(PRGDIR)/,rt_prg_,$(FUZZ_RT_OBJ5)) +FUZZ_RT_OBJ7 := $(subst $\./,rt_fuzz_,$(FUZZ_RT_OBJ6)) +FUZZ_ROUND_TRIP_OBJ := $(FUZZ_RT_OBJ7:.c=.o) .PHONY: default all clean cleanall @@ -75,45 +93,88 @@ FUZZ_TARGETS := \ dictionary_decompress \ zstd_frame_info \ simple_compress \ - dictionary_loader + dictionary_loader \ + raw_dictionary_round_trip all: $(FUZZ_TARGETS) -%.o: %.c - $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $^ -c -o $@ +rt_lib_common_%.o: $(ZSTDDIR)/common/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_lib_compress_%.o: $(ZSTDDIR)/compress/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_lib_decompress_%.o: $(ZSTDDIR)/decompress/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_lib_dictBuilder_%.o: $(ZSTDDIR)/dictBuilder/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_lib_legacy_%.o: $(ZSTDDIR)/legacy/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_prg_%.o: $(PRGDIR)/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +rt_fuzz_%.o: %.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $(FUZZ_ROUND_TRIP_FLAGS) $< -c -o $@ + +d_lib_common_%.o: $(ZSTDDIR)/common/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_lib_compress_%.o: $(ZSTDDIR)/compress/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_lib_decompress_%.o: $(ZSTDDIR)/decompress/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_lib_dictBuilder_%.o: $(ZSTDDIR)/dictBuilder/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_lib_legacy_%.o: $(ZSTDDIR)/legacy/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_prg_%.o: $(PRGDIR)/%.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +d_fuzz_%.o: %.c + $(CC) $(FUZZ_CPPFLAGS) $(FUZZ_CFLAGS) $< -c -o $@ + +simple_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_round_trip.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ -simple_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) simple_round_trip.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) simple_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ +stream_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_stream_round_trip.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_stream_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ -stream_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) stream_round_trip.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) stream_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ +block_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_block_round_trip.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_block_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ -block_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) block_round_trip.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) block_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ +simple_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_simple_decompress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_simple_decompress.o $(LIB_FUZZING_ENGINE) -o $@ -simple_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) simple_decompress.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) simple_decompress.o $(LIB_FUZZING_ENGINE) -o $@ +stream_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_stream_decompress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_stream_decompress.o $(LIB_FUZZING_ENGINE) -o $@ -stream_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) stream_decompress.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) stream_decompress.o $(LIB_FUZZING_ENGINE) -o $@ +block_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_block_decompress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_block_decompress.o $(LIB_FUZZING_ENGINE) -o $@ -block_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) block_decompress.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) block_decompress.o $(LIB_FUZZING_ENGINE) -o $@ +dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_round_trip.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ -dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_round_trip.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ +raw_dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@ -dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@ +dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@ -simple_compress: $(FUZZ_HEADERS) $(FUZZ_OBJ) simple_compress.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) simple_compress.o $(LIB_FUZZING_ENGINE) -o $@ +simple_compress: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_compress.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_simple_compress.o $(LIB_FUZZING_ENGINE) -o $@ -zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_OBJ) zstd_frame_info.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@ +zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_zstd_frame_info.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@ -dictionary_loader: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_loader.o - $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_loader.o $(LIB_FUZZING_ENGINE) -o $@ +dictionary_loader: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o + $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o $(LIB_FUZZING_ENGINE) -o $@ libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o $(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o @@ -136,7 +197,6 @@ regressiontest: corpora $(PYTHON) ./fuzz.py regression all clean: - @$(MAKE) -C $(ZSTDDIR) clean @$(RM) *.a *.o @$(RM) simple_round_trip stream_round_trip simple_decompress \ stream_decompress block_decompress block_round_trip \ diff --git a/tests/fuzz/fuzz.py b/tests/fuzz/fuzz.py index 52d41d2be37..29d26955733 100755 --- a/tests/fuzz/fuzz.py +++ b/tests/fuzz/fuzz.py @@ -57,6 +57,7 @@ def __init__(self, input_type, frame_type=FrameType.ZSTD): 'zstd_frame_info': TargetInfo(InputType.COMPRESSED_DATA), 'simple_compress': TargetInfo(InputType.RAW_DATA), 'dictionary_loader': TargetInfo(InputType.DICTIONARY_DATA), + 'raw_dictionary_round_trip': TargetInfo(InputType.RAW_DATA), } TARGETS = list(TARGET_INFO.keys()) ALL_TARGETS = TARGETS + ['all'] diff --git a/tests/fuzz/raw_dictionary_round_trip.c b/tests/fuzz/raw_dictionary_round_trip.c new file mode 100644 index 00000000000..08e5fd9edc1 --- /dev/null +++ b/tests/fuzz/raw_dictionary_round_trip.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016-2020, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/** + * This fuzz target performs a zstd round-trip test (compress & decompress) with + * a raw content dictionary, compares the result with the original, and calls + * abort() on corruption. + */ + +#include +#include +#include +#include +#include "fuzz_helpers.h" +#include "zstd_helpers.h" +#include "fuzz_data_producer.h" + +static ZSTD_CCtx *cctx = NULL; +static ZSTD_DCtx *dctx = NULL; + +static size_t roundTripTest(void *result, size_t resultCapacity, + void *compressed, size_t compressedCapacity, + const void *src, size_t srcSize, + const void *dict, size_t dictSize, + FUZZ_dataProducer_t *producer) +{ + ZSTD_dictContentType_e const dictContentType = ZSTD_dct_rawContent; + int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0; + size_t cSize; + + FUZZ_setRandomParameters(cctx, srcSize, producer); + /* Disable checksum so we can use sizes smaller than compress bound. */ + FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0)); + if (refPrefix) + FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced( + cctx, dict, dictSize, + ZSTD_dct_rawContent)); + else + FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( + cctx, dict, dictSize, + (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), + ZSTD_dct_rawContent)); + cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize); + FUZZ_ZASSERT(cSize); + + if (refPrefix) + FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced( + dctx, dict, dictSize, + dictContentType)); + else + FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( + dctx, dict, dictSize, + (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1), + dictContentType)); + { + size_t const ret = ZSTD_decompressDCtx( + dctx, result, resultCapacity, compressed, cSize); + return ret; + } +} + +int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) +{ + /* Give a random portion of src data to the producer, to use for + parameter generation. The rest will be used for (de)compression */ + FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); + size = FUZZ_dataProducer_reserveDataPrefix(producer); + + uint8_t const* const srcBuf = src; + size_t const srcSize = FUZZ_dataProducer_uint32Range(producer, 0, size); + uint8_t const* const dictBuf = srcBuf + srcSize; + size_t const dictSize = size - srcSize; + size_t const decompSize = srcSize; + void* const decompBuf = FUZZ_malloc(decompSize); + size_t compSize = ZSTD_compressBound(srcSize); + void* compBuf; + /* Half of the time fuzz with a 1 byte smaller output size. + * This will still succeed because we force the checksum to be disabled, + * giving us 4 bytes of overhead. + */ + compSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1); + compBuf = FUZZ_malloc(compSize); + + if (!cctx) { + cctx = ZSTD_createCCtx(); + FUZZ_ASSERT(cctx); + } + if (!dctx) { + dctx = ZSTD_createDCtx(); + FUZZ_ASSERT(dctx); + } + + { + size_t const result = + roundTripTest(decompBuf, decompSize, compBuf, compSize, srcBuf, srcSize, dictBuf, dictSize, producer); + FUZZ_ZASSERT(result); + FUZZ_ASSERT_MSG(result == srcSize, "Incorrect regenerated size"); + FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, decompBuf, srcSize), "Corruption!"); + } + free(decompBuf); + free(compBuf); + FUZZ_dataProducer_free(producer); +#ifndef STATEFUL_FUZZING + ZSTD_freeCCtx(cctx); cctx = NULL; + ZSTD_freeDCtx(dctx); dctx = NULL; +#endif + return 0; +} From 80d3585e314bb223b6c0647b3d3443a9257b1fc6 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 11 May 2020 19:04:30 -0700 Subject: [PATCH 369/402] [lib] Fix lazy parser with dictionary + repcodes --- lib/compress/zstd_lazy.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 81cdbc96fdb..def421e90ca 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -951,12 +951,13 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( size_t offset=0; const BYTE* start=ip+1; U32 current = (U32)(ip-base); + U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); /* check repCode */ { const U32 repIndex = (U32)(current+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ + if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip+1) == MEM_read32(repMatch)) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -981,12 +982,14 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( while (ipcParams.windowLog); /* check repCode */ if (offset) { const U32 repIndex = (U32)(current - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ + windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); + if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -1011,12 +1014,13 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( if ((depth==2) && (ipcParams.windowLog); /* check repCode */ if (offset) { const U32 repIndex = (U32)(current - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ + if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; @@ -1060,7 +1064,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const U32 repIndex = (U32)((ip-base) - offset_2); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ + windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); + if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected we should take it */ const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; From 76e726e3beb054a0e6d02d3314418277881a19f7 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 11 May 2020 19:21:50 -0700 Subject: [PATCH 370/402] updated documentation for ZSTD_estimate*() make it clearer that tighter memory estimation can be provided using advanced functions on the condition of a defined input size bound. --- lib/zstd.h | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/zstd.h b/lib/zstd.h index 18c20c87e3e..8c6fc6ae90e 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -274,9 +274,9 @@ typedef enum { * Default level is ZSTD_CLEVEL_DEFAULT==3. * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. * Note 1 : it's possible to pass a negative compression level. - * Note 2 : setting a level does not automatically set all other compression parameters - * to default. Setting this will however eventually dynamically impact the compression - * parameters which have not been manually set. The manually set + * Note 2 : setting a level does not automatically set all other compression parameters + * to default. Setting this will however eventually dynamically impact the compression + * parameters which have not been manually set. The manually set * ones will 'stick'. */ /* Advanced compression parameters : * It's possible to pin down compression parameters to some specific values. @@ -1268,23 +1268,28 @@ ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, ***************************************/ /*! ZSTD_estimate*() : - * These functions make it possible to estimate memory usage of a future - * {D,C}Ctx, before its creation. + * These functions make it possible to estimate memory usage + * of a future {D,C}Ctx, before its creation. * - * ZSTD_estimateCCtxSize() will provide a budget large enough for any - * compression level up to selected one. Unlike ZSTD_estimateCStreamSize*(), - * this estimate does not include space for a window buffer, so this estimate - * is guaranteed to be enough for single-shot compressions, but not streaming - * compressions. It will however assume the input may be arbitrarily large, - * which is the worst case. If srcSize is known to always be small, - * ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. - * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with - * ZSTD_getCParams() to create cParams from compressionLevel. - * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with - * ZSTD_CCtxParams_setParameter(). + * ZSTD_estimateCCtxSize() will provide a memory budget large enough + * for any compression level up to selected one. + * Note : Unlike ZSTD_estimateCStreamSize*(), this estimate + * does not include space for a window buffer. + * Therefore, the estimation is only guaranteed for single-shot compressions, not streaming. + * The estimate will assume the input may be arbitrarily large, + * which is the worst case. * - * Note: only single-threaded compression is supported. This function will - * return an error code if ZSTD_c_nbWorkers is >= 1. */ + * When srcSize can be bound by a known and rather "small" value, + * this fact can be used to provide a tighter estimation + * because the CCtx compression context will need less memory. + * This tighter estimation can be provided by more advanced functions + * ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(), + * and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter(). + * Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits. + * + * Note 2 : only single-threaded compression is supported. + * ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. + */ ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); From 20bd24604538fa3ac3c7147e54016c0e34a51267 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 11 May 2020 19:29:36 -0700 Subject: [PATCH 371/402] blindfix for VS macro redefinition --- lib/common/error_private.h | 2 +- tests/fuzzer.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/common/error_private.h b/lib/common/error_private.h index ced1a3ba978..982cf8e9fe6 100644 --- a/lib/common/error_private.h +++ b/lib/common/error_private.h @@ -49,7 +49,7 @@ typedef ZSTD_ErrorCode ERR_enum; /*-**************************************** * Error codes handling ******************************************/ -#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ +#undef ERROR /* already defined on Visual Studio */ #define ERROR(name) ZSTD_ERROR(name) #define ZSTD_ERROR(name) ((size_t)-PREFIX(name)) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 0202b331827..8bc27c0ba36 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -32,16 +32,17 @@ #include "fse.h" #include "zstd.h" /* ZSTD_VERSION_STRING */ #include "zstd_errors.h" /* ZSTD_getErrorCode */ -#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ #include "zstdmt_compress.h" #define ZDICT_STATIC_LINKING_ONLY #include "zdict.h" /* ZDICT_trainFromBuffer */ -#include "datagen.h" /* RDG_genBuffer */ #include "mem.h" +#include "datagen.h" /* RDG_genBuffer */ #define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ #include "xxhash.h" /* XXH64 */ #include "util.h" #include "timefn.h" /* SEC_TO_MICRO, UTIL_time_t, UTIL_TIME_INITIALIZER, UTIL_clockSpanMicro, UTIL_getTime */ +/* must be included after util.h, due to ERROR macro redefinition issue on Visual Studio */ +#include "zstd_internal.h" /* ZSTD_WORKSPACETOOLARGE_MAXDURATION, ZSTD_WORKSPACETOOLARGE_FACTOR, KB, MB */ /*-************************************ From e001715b3d3e4c8bb8a99b928b9e8614d4b63f42 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 11 May 2020 20:35:47 -0700 Subject: [PATCH 372/402] fixed asan test --- tests/fuzzer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 8bc27c0ba36..9b01bc9449e 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1087,7 +1087,6 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_DCtx* const staticDCtx = ZSTD_initStaticDCtx(staticDCtxBuffer, staticDCtxSize); DISPLAYLEVEL(4, "Full CCtx size = %u, ", (U32)staticCCtxSize); DISPLAYLEVEL(4, "CCtx for 32 KB = %u, ", (U32)smallCCtxSize); - assert(staticCCtxSize > smallCCtxSize * ZSTD_WORKSPACETOOLARGE_FACTOR); /* ensure size down scenario */ if ((staticCCtx==NULL) || (staticDCtx==NULL)) goto _output_error; DISPLAYLEVEL(3, "OK \n"); @@ -1108,7 +1107,8 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : resize context to full CCtx size : ", testNb++); staticCCtx = ZSTD_initStaticCStream(staticCCtxBuffer, staticCCtxSize); - if ((void*)staticCCtx != staticCCtxBuffer) goto _output_error; + DISPLAYLEVEL(4, "staticCCtxBuffer = %p, staticCCtx = %p , ", staticCCtxBuffer, staticCCtx); + if (staticCCtx == NULL) goto _output_error; DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : compress large input with static CCtx : ", testNb++); @@ -1120,6 +1120,7 @@ static int basicUnitTests(U32 const seed, double compressibility) DISPLAYLEVEL(3, "test%3i : compress small input often enough to trigger context reduce : ", testNb++); { int nbc; + assert(staticCCtxSize > smallCCtxSize * ZSTD_WORKSPACETOOLARGE_FACTOR); /* ensure size down scenario */ assert(CNBuffSize > smallInSize + ZSTD_WORKSPACETOOLARGE_MAXDURATION + 3); for (nbc=0; nbc Date: Mon, 11 May 2020 19:05:42 -0700 Subject: [PATCH 373/402] [lib][fuzz] Assert sequences are valid in round trip tests --- lib/compress/zstd_lazy.c | 15 ++-- lib/decompress/zstd_ddict.c | 3 + lib/decompress/zstd_decompress.c | 6 ++ lib/decompress/zstd_decompress_block.c | 96 ++++++++++++++++++----- lib/decompress/zstd_decompress_internal.h | 4 + tests/fuzz/Makefile | 4 +- 6 files changed, 99 insertions(+), 29 deletions(-) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index def421e90ca..65ad2f27f8c 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -929,11 +929,11 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( const BYTE* const ilimit = iend - 8; const BYTE* const base = ms->window.base; const U32 dictLimit = ms->window.dictLimit; - const U32 lowestIndex = ms->window.lowLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictBase = ms->window.dictBase; const BYTE* const dictEnd = dictBase + dictLimit; - const BYTE* const dictStart = dictBase + lowestIndex; + const BYTE* const dictStart = dictBase + ms->window.lowLimit; + const U32 windowLog = ms->cParams.windowLog; typedef size_t (*searchMax_f)( ZSTD_matchState_t* ms, @@ -951,10 +951,10 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( size_t offset=0; const BYTE* start=ip+1; U32 current = (U32)(ip-base); - U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); /* check repCode */ - { const U32 repIndex = (U32)(current+1 - offset_1); + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); + const U32 repIndex = (U32)(current+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ @@ -982,13 +982,12 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( while (ipcParams.windowLog); /* check repCode */ if (offset) { + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); const U32 repIndex = (U32)(current - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected */ @@ -1014,9 +1013,9 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( if ((depth==2) && (ipcParams.windowLog); /* check repCode */ if (offset) { + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); const U32 repIndex = (U32)(current - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; @@ -1061,10 +1060,10 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( /* check immediate repcode */ while (ip <= ilimit) { + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); const U32 repIndex = (U32)((ip-base) - offset_2); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - windowLow = ZSTD_getLowestMatchIndex(ms, current, ms->cParams.windowLog); if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ if (MEM_read32(ip) == MEM_read32(repMatch)) { /* repcode detected we should take it */ diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index 042a7bc855c..b0e025e7aae 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -65,6 +65,9 @@ void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) dctx->virtualStart = ddict->dictContent; dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize; dctx->previousDstEnd = dctx->dictEnd; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dctx->dictContentEndForFuzzing = dctx->previousDstEnd; +#endif if (ddict->entropyPresent) { dctx->litEntropy = 1; dctx->fseEntropy = 1; diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 90ddeaabe18..d8f6eb7db05 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -114,6 +114,9 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); dctx->outBufferMode = ZSTD_obm_buffered; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dctx->dictContentEndForFuzzing = NULL; +#endif } ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) @@ -1039,6 +1042,9 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); dctx->prefixStart = dict; dctx->previousDstEnd = (const char*)dict + dictSize; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dctx->dictContentEndForFuzzing = dctx->previousDstEnd; +#endif return 0; } diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index 3b9ba37717b..b2a10c0d894 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -947,13 +947,52 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c return seq; } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) +{ + size_t const windowSize = dctx->fParams.windowSize; + /* No dictionary used. */ + if (dctx->dictContentEndForFuzzing == NULL) return 0; + /* Dictionary is not our ext-dict. */ + if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0; + /* Dictionary is not within our window size. */ + if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0; + /* Dictionary is active. */ + return 1; +} + +MEM_STATIC void ZSTD_assertValidSequence( + ZSTD_DCtx const* dctx, + BYTE const* op, BYTE const* oend, + seq_t const seq, + BYTE const* prefixStart, BYTE const* virtualStart) +{ + size_t const windowSize = dctx->fParams.windowSize; + size_t const sequenceSize = seq.litLength + seq.matchLength; + BYTE const* const oLitEnd = op + seq.litLength; + assert(op <= oend); + assert((size_t)(oend - op) >= sequenceSize); + assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX); + if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) { + size_t const dictSize = (size_t)(prefixStart - virtualStart); + /* Offset must be within the dictionary. */ + assert(seq.offset <= (size_t)(oLitEnd - virtualStart)); + assert(seq.offset <= windowSize + dictSize); + } else { + /* Offset must be within our window. */ + assert(seq.offset <= windowSize); + } +} +#endif + #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG FORCE_INLINE_TEMPLATE size_t DONT_VECTORIZE ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset) + const ZSTD_longOffset_e isLongOffset, + const int frame) { const BYTE* ip = (const BYTE*)seqStart; const BYTE* const iend = ip + seqSize; @@ -966,6 +1005,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, const BYTE* const vBase = (const BYTE*) (dctx->virtualStart); const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); DEBUGLOG(5, "ZSTD_decompressSequences_body"); + (void)frame; /* Regen sequences */ if (nbSeq) { @@ -1030,6 +1070,9 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, for ( ; ; ) { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); +#endif DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); BIT_reloadDStream(&(seqState.DStream)); /* gcc and clang both don't like early returns in this loop. @@ -1068,9 +1111,10 @@ static size_t ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset) + const ZSTD_longOffset_e isLongOffset, + const int frame) { - return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); } #endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ @@ -1080,7 +1124,8 @@ ZSTD_decompressSequencesLong_body( ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset) + const ZSTD_longOffset_e isLongOffset, + const int frame) { const BYTE* ip = (const BYTE*)seqStart; const BYTE* const iend = ip + seqSize; @@ -1092,6 +1137,7 @@ ZSTD_decompressSequencesLong_body( const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart); const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); + (void)frame; /* Regen sequences */ if (nbSeq) { @@ -1127,6 +1173,9 @@ ZSTD_decompressSequencesLong_body( for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNbbmi2) { - return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); } #endif - return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); } #endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ @@ -1230,15 +1287,16 @@ static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset) + const ZSTD_longOffset_e isLongOffset, + const int frame) { DEBUGLOG(5, "ZSTD_decompressSequencesLong"); #if DYNAMIC_BMI2 if (dctx->bmi2) { - return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); } #endif - return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); } #endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ @@ -1333,12 +1391,12 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, if (usePrefetchDecoder) #endif #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT - return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); + return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame); #endif #ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG /* else */ - return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); + return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame); #endif } } diff --git a/lib/decompress/zstd_decompress_internal.h b/lib/decompress/zstd_decompress_internal.h index 8c4f79f465d..1aa1face09d 100644 --- a/lib/decompress/zstd_decompress_internal.h +++ b/lib/decompress/zstd_decompress_internal.h @@ -160,6 +160,10 @@ struct ZSTD_DCtx_s BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; size_t oversizedDuration; + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + void const* dictContentEndForFuzzing; +#endif }; /* typedef'd to ZSTD_DCtx within "zstd.h" */ diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile index 3c7dc09e22f..d71c34d6863 100644 --- a/tests/fuzz/Makefile +++ b/tests/fuzz/Makefile @@ -176,8 +176,8 @@ zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_zstd_frame_info.o dictionary_loader: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o $(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_loader.o $(LIB_FUZZING_ENGINE) -o $@ -libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o - $(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o +libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c d_fuzz_regression_driver.o + $(AR) $(FUZZ_ARFLAGS) $@ d_fuzz_regression_driver.o corpora/%_seed_corpus.zip: @mkdir -p corpora From 6d687a88160c50a94cf1dccb0fdbb0b60ea9d936 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Mon, 11 May 2020 22:27:34 -0700 Subject: [PATCH 374/402] [lib] Fix dictionary + repcodes + optimal parser --- lib/compress/zstd_opt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_opt.c b/lib/compress/zstd_opt.c index 890ae9243e1..36fff050cf5 100644 --- a/lib/compress/zstd_opt.c +++ b/lib/compress/zstd_opt.c @@ -569,7 +569,10 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 repLen = 0; assert(current >= dictLimit); if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */ - if (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch)) { + /* We must validate the repcode offset because when we're using a dictionary the + * valid offset range shrinks when the dictionary goes out of bounds. + */ + if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) { repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch; } } else { /* repIndex < dictLimit || repIndex >= current */ From 4e0515916d89abecfd157ed631ca3f39ba2fd042 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 12 May 2020 11:57:15 -0700 Subject: [PATCH 375/402] [lib] Fix repcode validation in no dict mode --- lib/compress/zstd_compress.c | 2 ++ lib/compress/zstd_compress_internal.h | 16 ++++++++++++++++ lib/compress/zstd_double_fast.c | 10 +++++----- lib/compress/zstd_fast.c | 8 ++++---- lib/compress/zstd_lazy.c | 6 +++++- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index ff8a00e6b3b..528ee9e5df6 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -3278,6 +3278,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, { ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0); ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); + DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); assert(params.fParams.contentSizeFlag == 1); return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams); } @@ -4053,6 +4054,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { + DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); { size_t oPos = 0; size_t iPos = 0; diff --git a/lib/compress/zstd_compress_internal.h b/lib/compress/zstd_compress_internal.h index 8a16c371a69..db73f6ce21f 100644 --- a/lib/compress/zstd_compress_internal.h +++ b/lib/compress/zstd_compress_internal.h @@ -970,6 +970,9 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, return contiguous; } +/** + * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. + */ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; @@ -980,6 +983,19 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current return matchLowest; } +/** + * Returns the lowest allowed match index in the prefix. + */ +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +{ + U32 const maxDistance = 1U << windowLog; + U32 const lowestValid = ms->window.dictLimit; + U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const isDictionary = (ms->loadedDictEnd != 0); + U32 const matchLowest = isDictionary ? lowestValid : withinWindow; + return matchLowest; +} + /* debug functions */ diff --git a/lib/compress/zstd_double_fast.c b/lib/compress/zstd_double_fast.c index 2306a0d8c46..27eed66cfed 100644 --- a/lib/compress/zstd_double_fast.c +++ b/lib/compress/zstd_double_fast.c @@ -63,10 +63,8 @@ size_t ZSTD_compressBlock_doubleFast_generic( const BYTE* ip = istart; const BYTE* anchor = istart; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 lowestValid = ms->window.dictLimit; - const U32 maxDistance = 1U << cParams->windowLog; /* presumes that, if there is a dictionary, it must be using Attach mode */ - const U32 prefixLowestIndex = (endIndex - lowestValid > maxDistance) ? endIndex - maxDistance : lowestValid; + const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); const BYTE* const prefixLowest = base + prefixLowestIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -104,13 +102,15 @@ size_t ZSTD_compressBlock_doubleFast_generic( /* if a dictionary is attached, it must be within window range */ if (dictMode == ZSTD_dictMatchState) { - assert(lowestValid + maxDistance >= endIndex); + assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex); } /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const maxRep = (U32)(ip - prefixLowest); + U32 const current = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); + U32 const maxRep = current - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c index 81c7cd2c808..9906e4ba287 100644 --- a/lib/compress/zstd_fast.c +++ b/lib/compress/zstd_fast.c @@ -61,9 +61,7 @@ ZSTD_compressBlock_fast_generic( const BYTE* ip1; const BYTE* anchor = istart; const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 maxDistance = 1U << cParams->windowLog; - const U32 validStartIndex = ms->window.dictLimit; - const U32 prefixStartIndex = (endIndex - validStartIndex > maxDistance) ? endIndex - maxDistance : validStartIndex; + const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); const BYTE* const prefixStart = base + prefixStartIndex; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - HASH_READ_SIZE; @@ -74,7 +72,9 @@ ZSTD_compressBlock_fast_generic( DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); ip1 = ip0 + 1; - { U32 const maxRep = (U32)(ip0 - prefixStart); + { U32 const current = (U32)(ip0 - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); + U32 const maxRep = current - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 65ad2f27f8c..55bf23c89cf 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -662,10 +662,14 @@ ZSTD_compressBlock_lazy_generic( 0; const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); + DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u)", (U32)dictMode); + /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const maxRep = (U32)(ip - prefixLowest); + U32 const current = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, ms->cParams.windowLog); + U32 const maxRep = current - windowLow; if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0; if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0; } From 3c1eba4d9919708ab1f0cf58c1f9dced6b0af82d Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 12 May 2020 12:25:06 -0700 Subject: [PATCH 376/402] [lib] Fix lazy repcode validity checks --- lib/compress/zstd_lazy.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 55bf23c89cf..67ed07cba7a 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -946,6 +946,8 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( U32 offset_1 = rep[0], offset_2 = rep[1]; + DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic"); + /* init */ ip += (ip == prefixStart); @@ -957,7 +959,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( U32 current = (U32)(ip-base); /* check repCode */ - { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current+1, windowLog); const U32 repIndex = (U32)(current+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; @@ -1064,8 +1066,9 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( /* check immediate repcode */ while (ip <= ilimit) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); - const U32 repIndex = (U32)((ip-base) - offset_2); + const U32 repCurrent = (U32)(ip-base); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog); + const U32 repIndex = repCurrent - offset_2; const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ From 0453cfa8f584d6a85134e225be4cbd6461c02e3b Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Tue, 12 May 2020 15:18:43 -0500 Subject: [PATCH 377/402] removing -f test (grep usage not supported on mac) --- tests/playTests.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/playTests.sh b/tests/playTests.sh index 90575c0cc77..260213114cd 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -254,14 +254,6 @@ ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst && die "Should have failed ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst | grep "No such file or directory" || true rm -f tmp_grep* -println "\n===> zstdgrep pipe in with -f " -echo "start" > tmp_grep -echo "stop" >> tmp_grep -echo "start" | ZCAT=./zstdcat $ZSTDGREP -f - tmp_grep > tmp_grep_out1 -echo "start" | grep -f - tmp_grep > tmp_grep_out2 -$DIFF tmp_grep_out1 tmp_grep_out2 -rm -f tmp_grep* - println "\n===> zstdgrep --regexp= multiple" echo "start" > tmp_grep echo "stop" >> tmp_grep From f800e72a3c04604475dcfbb337c4fe0cdd430ead Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 12 May 2020 14:33:59 -0700 Subject: [PATCH 378/402] [lib] Fix assertion when dictionary is prefix --- lib/decompress/zstd_ddict.c | 1 + lib/decompress/zstd_decompress.c | 1 + lib/decompress/zstd_decompress_block.c | 9 ++++++++- lib/decompress/zstd_decompress_internal.h | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/decompress/zstd_ddict.c b/lib/decompress/zstd_ddict.c index b0e025e7aae..c8cb8ecc952 100644 --- a/lib/decompress/zstd_ddict.c +++ b/lib/decompress/zstd_ddict.c @@ -66,6 +66,7 @@ void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize; dctx->previousDstEnd = dctx->dictEnd; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dctx->dictContentBeginForFuzzing = dctx->prefixStart; dctx->dictContentEndForFuzzing = dctx->previousDstEnd; #endif if (ddict->entropyPresent) { diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index d8f6eb7db05..be5c7cfc334 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -1043,6 +1043,7 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict dctx->prefixStart = dict; dctx->previousDstEnd = (const char*)dict + dictSize; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + dctx->dictContentBeginForFuzzing = dctx->prefixStart; dctx->dictContentEndForFuzzing = dctx->previousDstEnd; #endif return 0; diff --git a/lib/decompress/zstd_decompress_block.c b/lib/decompress/zstd_decompress_block.c index b2a10c0d894..ad3b3d8dbd0 100644 --- a/lib/decompress/zstd_decompress_block.c +++ b/lib/decompress/zstd_decompress_block.c @@ -953,6 +953,8 @@ static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStar size_t const windowSize = dctx->fParams.windowSize; /* No dictionary used. */ if (dctx->dictContentEndForFuzzing == NULL) return 0; + /* Dictionary is our prefix. */ + if (prefixStart == dctx->dictContentBeginForFuzzing) return 1; /* Dictionary is not our ext-dict. */ if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0; /* Dictionary is not within our window size. */ @@ -970,11 +972,13 @@ MEM_STATIC void ZSTD_assertValidSequence( size_t const windowSize = dctx->fParams.windowSize; size_t const sequenceSize = seq.litLength + seq.matchLength; BYTE const* const oLitEnd = op + seq.litLength; + DEBUGLOG(6, "Checking sequence: litL=%u matchL=%u offset=%u", + (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); assert(op <= oend); assert((size_t)(oend - op) >= sequenceSize); assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX); if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) { - size_t const dictSize = (size_t)(prefixStart - virtualStart); + size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing); /* Offset must be within the dictionary. */ assert(seq.offset <= (size_t)(oLitEnd - virtualStart)); assert(seq.offset <= windowSize + dictSize); @@ -1071,6 +1075,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); #endif DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); @@ -1174,6 +1179,7 @@ ZSTD_decompressSequencesLong_body( seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch); size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd); #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart); #endif if (ZSTD_isError(oneSeqSize)) return oneSeqSize; @@ -1188,6 +1194,7 @@ ZSTD_decompressSequencesLong_body( for ( ; seqNb Date: Tue, 12 May 2020 17:51:16 -0700 Subject: [PATCH 379/402] [greedy] Fix performance instability --- lib/compress/zstd_lazy.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/compress/zstd_lazy.c b/lib/compress/zstd_lazy.c index 67ed07cba7a..4cf5c88b532 100644 --- a/lib/compress/zstd_lazy.c +++ b/lib/compress/zstd_lazy.c @@ -681,6 +681,12 @@ ZSTD_compressBlock_lazy_generic( } /* Match Loop */ +#if defined(__GNUC__) && defined(__x86_64__) + /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the + * code alignment is perturbed. To fix the instability align the loop on 32-bytes. + */ + __asm__(".p2align 5"); +#endif while (ip < ilimit) { size_t matchLength=0; size_t offset=0; @@ -952,6 +958,12 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( ip += (ip == prefixStart); /* Match Loop */ +#if defined(__GNUC__) && defined(__x86_64__) + /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the + * code alignment is perturbed. To fix the instability align the loop on 32-bytes. + */ + __asm__(".p2align 5"); +#endif while (ip < ilimit) { size_t matchLength=0; size_t offset=0; From 9b13077cfb4d7fa6adf9de83b6444d661edb89af Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 13 May 2020 15:12:14 -0500 Subject: [PATCH 380/402] Revert to old zstdgrep --- programs/zstdgrep | 228 +++++++++++++++++----------------------------- 1 file changed, 82 insertions(+), 146 deletions(-) diff --git a/programs/zstdgrep b/programs/zstdgrep index 60d5fe16d1e..61efaa9474a 100755 --- a/programs/zstdgrep +++ b/programs/zstdgrep @@ -28,6 +28,8 @@ zcat=${ZCAT:-zstdcat} endofopts=0 pattern_found=0 grep_args="" +hyphen=0 +silent=0 prog=${0##*/} @@ -41,158 +43,92 @@ esac # skip all options and pass them on to grep taking care of options # with arguments, and if -e was supplied -escape=' - s/'\''/'\''\\'\'''\''/g - $s/$/'\''/ -' - -# We might want to create a c program in the future -# and replace this file with that if these -# unsupported options become necessary -usage="Usage: $0 [OPTION]... [-e] PATTERN [FILE]... -OPTIONs are the same as grep with the exception of -the following unsupported options: - --dereference-recursive (-R) - --directories (-d) - --exclude - --exclude-from - --exclude-dir - --include - --null (-Z), - --null-data (-z) - --recursive (-r) -grep --help below: -" - -operands= -files_with_matches=0 -files_without_matches=0 -no_filename=0 -with_filename=0 - while [ "$#" -gt 0 ] && [ "${endofopts}" -eq 0 ]; do - option=$1 - shift - optarg= - - case $option in - (-[0123456789EFGHIKLPRTUVZabchilnoqrsuvwxyz]?*) - arg2=-\'$(expr "X$option" : 'X-.[0-9]*\(.*\)' | sed "$escape") - eval "set -- $arg2 "'${1+"$@"}' - option=$(expr "X$option" : 'X\(-.[0-9]*\)');; - (--binary-*=* | --[lm]a*=* | --reg*=*) ;; - (-[ABCDXdefm] | binary-* | --file | --[lm]a* | --reg*) - case ${1?"$option option requires an argument"} in - (*\'*) optarg=" '"$(printf '%s\n' "$1" | sed "$escape");; - (*) optarg=" '$1'";; - esac - shift;; - (-f?*\'*) optarg=" '"$(expr "X$option" : 'X-f\(.*\)' | sed "$escape"); option=-f;; - (-f?*) optarg=" '"$(expr "X$option" : 'X-f\(.*\)')\'; option=-f;; - (--file=*\'*) optarg=" '"$(expr "X$option" : 'X--file=\(.*\)' | sed "$escape"); option=--file;; - (--file=*) optarg=" '"$(expr "X$option" : 'X--file=\(.*\)')\'; option=--file;; - (--) endofopts=1; break;; - (-?*) ;; - (*) - case $option in - (*\'*) operands="$operands '"$(printf '%s\n' "$option" | sed "$escape");; - (*) operands="$operands '$option'";; + case "$1" in + # from GNU grep-2.5.1 -- keep in sync! + -[ABCDXdefm]) + if [ "$#" -lt 2 ]; then + printf '%s: missing argument for %s flag\n' "${prog}" "$1" >&2 + exit 1 + fi + case "$1" in + -e) + pattern="$2" + pattern_found=1 + shift 2 + break + ;; + -f) + pattern_found=2 + ;; + *) + ;; esac - ${POSIXLY_CORRECT+break} + grep_args="${grep_args} $1 $2" + shift 2 + ;; + --) + shift endofopts=1 - continue;; - esac - - case $option in - (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*) - printf >&2 '%s: %s: option not supported\n' "$0" "$option" - exit 2;; - (-e* | --reg*) pattern_found=1;; - (-f | --file) - case $optarg in - (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'") - option=-e - optarg=" '"$(sed "$escape") || exit 2;; - esac - pattern_found=1;; - (--h | --he | --hel | --help) echo "$usage"; eval "$grep --help" || exit 2; exit;; - (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \ - | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \ - | --with-filename) - with_filename=1 - continue;; - (-l | --files-with-*) files_with_matches=1;; - (-L | --files-witho*) files_without_matches=1;; - (-h | --no-f*) no_filename=1;; - esac - - case $option in - (*\'?*) option=\'$(printf '%s\n' "$option" | sed "$escape");; - (*) option="'$option'";; - esac - - grep_args="$option$optarg" - grep="$grep $grep_args" - done - -eval "set -- $operands "'${1+"$@"}' - -if test $pattern_found -eq 0; then - case ${1?"missing pattern; try \`$0 --help' for help"} in - (*\'*) grep="$grep -- '"$(printf '%s\n' "$1" | sed "$escape");; - (*) grep="$grep -- '$1'";; + ;; + -) + hyphen=1 + shift + ;; + -h) + silent=1 + shift + ;; + -*) + grep_args="${grep_args} $1" + shift + ;; + *) + # pattern to grep for + endofopts=1 + ;; esac - shift -fi +done -if test $# -eq 0; then - set -- - +# if no -e option was found, take next argument as grep-pattern +if [ "${pattern_found}" -lt 1 ]; then + if [ "$#" -ge 1 ]; then + pattern="$1" + shift + elif [ "${hyphen}" -gt 0 ]; then + pattern="-" + else + printf '%s: missing pattern\n' "${prog}" >&2 + exit 1 + fi fi -exec 3>&1 -res=0 - -for i do - zcat_status=$( - exec 5>&1 - ($zcat -- "$i" 5>&-; echo $? >&5) 3>&- | - if test $files_with_matches -eq 1; then - eval "$grep" >/dev/null && { printf '%s\n' "$i" || exit 2; } - elif test $files_without_matches -eq 1; then - eval "$grep" >/dev/null || { - r=$? - if test $r -eq 1; then - printf '%s\n' "$i" || r=2 - fi - exit $r - } - elif test $with_filename -eq 0 && { test $# -eq 1 || test $no_filename -eq 1; }; then - eval "$grep" +EXIT_CODE=0 +# call grep ... +if [ "$#" -lt 1 ]; then + # ... on stdin + set -f # Disable file name generation (globbing). + # shellcheck disable=SC2086 + "${zcat}" - | "${grep}" ${grep_args} -- "${pattern}" - + EXIT_CODE=$? + set +f +else + # ... on all files given on the command line + if [ "${silent}" -lt 1 ] && [ "$#" -gt 1 ]; then + grep_args="-H ${grep_args}" + fi + set -f + while [ "$#" -gt 0 ]; do + # shellcheck disable=SC2086 + if [ $pattern_found -eq 2 ]; then + "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- - else - case $i in - (*' - '* | *'&'* | *'\'* | *'|'*) - i=$(printf '%s\n' "$i" | - sed ' - $!N - $s/[&\|]/\\&/g - $s/\n/\\n/g - ');; - esac - sed_script="s|^|$i:|" + "${zcat}" -- "$1" | "${grep}" --label="${1}" ${grep_args} -- "${pattern}" - + fi + [ "$?" -ne 0 ] && EXIT_CODE=1 + shift + done + set +f +fi - # Fail if grep or sed fails. - r=$( - exec 4>&1 - (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&- - ) && exit $r - r=$? - test 1 -lt $r && exit $r || exit 2 - fi >&3 5>&- - ) - r=$? - test 128 -lt $r && exit $r - test "$zcat_status" -eq 0 || test "$zcat_status" -eq 2 || r=2 - test $res -lt $r && res=$r -done -exit $res +exit "${EXIT_CODE}" From 12071467d307fdae29620e2b7871984166aa1d11 Mon Sep 17 00:00:00 2001 From: Bimba Shrestha Date: Wed, 13 May 2020 15:22:07 -0500 Subject: [PATCH 381/402] reverting docs and test --- programs/README.md | 13 ------------- tests/playTests.sh | 24 ------------------------ 2 files changed, 37 deletions(-) diff --git a/programs/README.md b/programs/README.md index 63ce79fc18f..53706de727b 100644 --- a/programs/README.md +++ b/programs/README.md @@ -272,19 +272,6 @@ It's used the same way as normal `grep`, for example : `zstdgrep pattern file.zst` `zstdgrep` is _not_ compatible with dictionary compression. -`zstdgrep` does not support the following grep options - -``` ---dereference-recursive (-R) - --directories (-d) - --exclude - --exclude-from - --exclude-dir - --include - --null (-Z), - --null-data (-z) - --recursive (-r) -``` To search into a file compressed with a dictionary, it's necessary to decompress it using `zstd` or `zstdcat`, diff --git a/tests/playTests.sh b/tests/playTests.sh index 260213114cd..3c91b958f18 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -254,30 +254,6 @@ ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst && die "Should have failed ZCAT=./zstdcat $ZSTDGREP 2>&1 "1234" tmp_grep_bad.zst | grep "No such file or directory" || true rm -f tmp_grep* -println "\n===> zstdgrep --regexp= multiple" -echo "start" > tmp_grep -echo "stop" >> tmp_grep -ZCAT=./zstdcat $ZSTDGREP --regexp=start --regexp=stop tmp_grep > tmp_grep_out1 -grep -e start -e stop tmp_grep > tmp_grep_out2 -$DIFF tmp_grep_out1 tmp_grep_out2 -rm -f tmp_grep* - -println "\n===> zstdgrep multiple -e" -echo "start" > tmp_grep -echo "stop" >> tmp_grep -ZCAT=./zstdcat $ZSTDGREP -e start -e stop tmp_grep > tmp_grep_out1 -grep -e start -e stop tmp_grep > tmp_grep_out2 -$DIFF tmp_grep_out1 tmp_grep_out2 -rm -f tmp_grep* - -println "\n===> zstdgrep multiple --regexp" -echo "start" > tmp_grep -echo "stop" >> tmp_grep -ZCAT=./zstdcat $ZSTDGREP --regexp start --regexp stop tmp_grep > tmp_grep_out1 -grep -e start -e stop tmp_grep > tmp_grep_out2 -$DIFF tmp_grep_out1 tmp_grep_out2 -rm -f tmp_grep* - println "\n===> --exclude-compressed flag" rm -rf precompressedFilterTestDir mkdir -p precompressedFilterTestDir From add7ed2d4a09c94e5a5b3b80682a858cbb3ecba1 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 14 May 2020 11:50:48 -0700 Subject: [PATCH 382/402] [lib] Fix bug in loading LDM dictionary in MT mode Exposed when loading a dictionary < LDM minMatch bytes in MT mode. Test Plan: ``` CC=clang make -j zstreamtest MOREFLAGS="-O0 -fsanitize=address" ./zstreamtest -vv -i100000000 -t1 --newapi -s7065 -t3925297 ``` TODO: Add an explicit test that loads a small dictionary in MT mode --- lib/compress/zstd_compress.c | 2 +- lib/compress/zstd_ldm.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index 33c3b4ecb63..2cfa93051fd 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2846,7 +2846,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk); - if (params->ldmParams.enableLdm && ls != NULL && srcSize >= params->ldmParams.minMatchLength) + if (params->ldmParams.enableLdm && ls != NULL) ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams); switch(params->cParams.strategy) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 2a1c2cd6287..22f3628070a 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -228,11 +228,13 @@ void ZSTD_ldm_fillHashTable( ldmState_t* state, const BYTE* ip, const BYTE* iend, ldmParams_t const* params) { - U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength); - ZSTD_ldm_fillLdmHashTable( - state, startingHash, ip, iend - params->minMatchLength, state->window.base, - params->hashLog - params->bucketSizeLog, - *params); + if ((size_t)(iend - ip) >= params->minMatchLength) { + U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength); + ZSTD_ldm_fillLdmHashTable( + state, startingHash, ip, iend - params->minMatchLength, state->window.base, + params->hashLog - params->bucketSizeLog, + *params); + } } From bf0591e1e25a8ee7f524fceac286cb35eac67e3f Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Thu, 14 May 2020 12:06:55 -0700 Subject: [PATCH 383/402] [test] Expose the LDM+MT+dict bug in a unit test --- tests/fuzzer.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 9b01bc9449e..bbbcb31addc 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2697,6 +2697,35 @@ static int basicUnitTests(U32 const seed, double compressibility) free(dict); } DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : small dictionary with multithreading and LDM ", testNb++); + { + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + /* A little more than ZSTDMT_JOBSIZE_MIN */ + size_t const srcSize = 1 MB + 5; + size_t const dictSize = 10; + size_t const dstSize = ZSTD_compressBound(srcSize); + void* const src = CNBuffer; + void* const dst = compressedBuffer; + void* dict = (void*)malloc(dictSize); + + RDG_genBuffer(src, srcSize, compressibility, 0.5, seed); + RDG_genBuffer(dict, dictSize, compressibility, 0., seed); + + /* Make sure there is no ZSTD_MAGIC_NUMBER */ + memset(dict, 0, sizeof(U32)); + + /* Enable MT, LDM, and use refPrefix() for a small dict */ + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1)); + CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize)); + + CHECK_Z(ZSTD_compress2(cctx, dst, dstSize, src, srcSize)); + + ZSTD_freeCCtx(cctx); + free(dict); + } + DISPLAYLEVEL(3, "OK \n"); #endif /* note : this test is rather long, it would be great to find a way to speed up its execution */ From f22b371e314e96456fdeca6310d96a78ba019cc3 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 14 May 2020 16:17:03 -0700 Subject: [PATCH 384/402] updated documentation for v1.4.5 API manual and man pages --- doc/zstd_manual.html | 54 ++++++++++++++++++++++++++------------------ programs/zstd.1 | 14 ++++++------ programs/zstdgrep.1 | 2 +- programs/zstdless.1 | 2 +- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index 43c5555b8ca..fe58f78cb15 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -1,10 +1,10 @@ -zstd 1.4.4 Manual +zstd 1.4.5 Manual -

zstd 1.4.4 Manual

+

zstd 1.4.5 Manual


Contents

    @@ -217,7 +217,10 @@

    Decompression context

      When decompressing many times,
                                   * Default level is ZSTD_CLEVEL_DEFAULT==3.
                                   * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
                                   * Note 1 : it's possible to pass a negative compression level.
    -                              * Note 2 : setting a level resets all other compression parameters to default */
    +                              * Note 2 : setting a level does not automatically set all other compression parameters
    +                              *   to default. Setting this will however eventually dynamically impact the compression
    +                              *   parameters which have not been manually set. The manually set
    +                              *   ones will 'stick'. */
         /* Advanced compression parameters :
          * It's possible to pin down compression parameters to some specific values.
          * In which case, these values are no longer dynamically selected by the compressor */
    @@ -451,11 +454,13 @@ 

    Decompression context

      When decompressing many times,
         /* note : additional experimental parameters are also available
          * within the experimental section of the API.
          * At the time of this writing, they include :
    -     * ZSTD_c_format
    +     * ZSTD_d_format
    +     * ZSTD_d_stableOutBuffer
          * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
          * note : never ever use experimentalParam? names directly
          */
    -     ZSTD_d_experimentalParam1=1000
    +     ZSTD_d_experimentalParam1=1000,
    +     ZSTD_d_experimentalParam2=1001
     
     } ZSTD_dParameter;
     

    @@ -1055,23 +1060,28 @@

    Streaming decompression functions


    size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); size_t ZSTD_estimateDCtxSize(void); -

    These functions make it possible to estimate memory usage of a future - {D,C}Ctx, before its creation. - - ZSTD_estimateCCtxSize() will provide a budget large enough for any - compression level up to selected one. Unlike ZSTD_estimateCStreamSize*(), - this estimate does not include space for a window buffer, so this estimate - is guaranteed to be enough for single-shot compressions, but not streaming - compressions. It will however assume the input may be arbitrarily large, - which is the worst case. If srcSize is known to always be small, - ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. - ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with - ZSTD_getCParams() to create cParams from compressionLevel. - ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with - ZSTD_CCtxParams_setParameter(). - - Note: only single-threaded compression is supported. This function will - return an error code if ZSTD_c_nbWorkers is >= 1. +

    These functions make it possible to estimate memory usage + of a future {D,C}Ctx, before its creation. + + ZSTD_estimateCCtxSize() will provide a memory budget large enough + for any compression level up to selected one. + Note : Unlike ZSTD_estimateCStreamSize*(), this estimate + does not include space for a window buffer. + Therefore, the estimation is only guaranteed for single-shot compressions, not streaming. + The estimate will assume the input may be arbitrarily large, + which is the worst case. + + When srcSize can be bound by a known and rather "small" value, + this fact can be used to provide a tighter estimation + because the CCtx compression context will need less memory. + This tighter estimation can be provided by more advanced functions + ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(), + and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter(). + Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits. + + Note 2 : only single-threaded compression is supported. + ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. +


    size_t ZSTD_estimateCStreamSize(int compressionLevel);
    diff --git a/programs/zstd.1 b/programs/zstd.1
    index 4d146034e8d..9ba0b4fa416 100644
    --- a/programs/zstd.1
    +++ b/programs/zstd.1
    @@ -1,5 +1,5 @@
     .
    -.TH "ZSTD" "1" "February 2020" "zstd 1.4.5" "User Commands"
    +.TH "ZSTD" "1" "May 2020" "zstd 1.4.5" "User Commands"
     .
     .SH "NAME"
     \fBzstd\fR \- zstd, zstdmt, unzstd, zstdcat \- Compress or decompress \.zst files
    @@ -114,7 +114,7 @@ Note: If \fBwindowLog\fR is set to larger than 27, \fB\-\-long=windowLog\fR or \
     \fB\-\-patch\-from=FILE\fR: Specify the file to be used as a reference point for zstd\'s diff engine\. This is effectively dictionary compression with some convenient parameter selection, namely that windowSize > srcSize\.
     .
     .IP
    -Note: cannot use both this and \-D together
    +Note: cannot use both this and \-D together Note: \fB\-\-long\fR mode will be automatically activated if chainLog < fileLog (fileLog being the windowLog requried to cover the whole file)\. You can also manually force it\. Node: for all levels, you can use \-\-patch\-from in \-\-single\-thread mode to improve compression ratio at the cost of speed Note: for level 19, you can get increased compression ratio at the cost of speed by specifying \fB\-\-zstd=targetLength=\fR to be something large (i\.e 4096), and by setting a large \fB\-\-zstd=chainLog=\fR
     .
     .IP "\(bu" 4
     \fB\-M#\fR, \fB\-\-memory=#\fR: Set a memory usage limit\. By default, Zstandard uses 128 MB for decompression as the maximum amount of memory the decompressor is allowed to use, but you can override this manually if need be in either direction (ie\. you can increase or decrease it)\.
    @@ -159,6 +159,9 @@ This is also used during compression when using with \-\-patch\-from=\. In this
     \fB\-\-[no\-]sparse\fR: enable / disable sparse FS support, to make files with many zeroes smaller on disk\. Creating sparse files may save disk space and speed up decompression by reducing the amount of disk I/O\. default: enabled when output is into a file, and disabled when output is stdout\. This setting overrides default and can force sparse mode over stdout\.
     .
     .IP "\(bu" 4
    +\fB\-\-[no\-]content\-size\fR: enable / disable whether or not the original size of the file is placed in the header of the compressed file\. The default option is \-\-content\-size (meaning that the original size will be placed in the header)\.
    +.
    +.IP "\(bu" 4
     \fB\-\-rm\fR: remove source file(s) after successful compression or decompression
     .
     .IP "\(bu" 4
    @@ -386,14 +389,11 @@ Larger search lengths usually decrease compression ratio but improve decompressi
     The minimum \fImml\fR is 3 and the maximum is 7\.
     .
     .TP
    -\fBtargetLen\fR=\fItlen\fR, \fBtlen\fR=\fItlen\fR
    +\fBtargetLength\fR=\fItlen\fR, \fBtlen\fR=\fItlen\fR
     The impact of this field vary depending on selected strategy\.
     .
     .IP
    -For ZSTD_btopt, ZSTD_btultra and ZSTD_btultra2, it specifies the minimum match length that causes match finder to stop searching\. A larger \fBtargetLen\fR usually improves compression ratio but decreases compression speed\.
    -.
    -.IP
    -For ZSTD_fast, it triggers ultra\-fast mode when > 0\. The value represents the amount of data skipped between match sampling\. Impact is reversed : a larger \fBtargetLen\fR increases compression speed but decreases compression ratio\.
    +For ZSTD_btopt, ZSTD_btultra and ZSTD_btultra2, it specifies the minimum match length that causes match finder to stop searching\. A larger \fBtargetLength\fR usually improves compression ratio but decreases compression speed\. t For ZSTD_fast, it triggers ultra\-fast mode when > 0\. The value represents the amount of data skipped between match sampling\. Impact is reversed : a larger \fBtargetLength\fR increases compression speed but decreases compression ratio\.
     .
     .IP
     For all other strategies, this field has no impact\.
    diff --git a/programs/zstdgrep.1 b/programs/zstdgrep.1
    index 5718e998e25..fe1d29bbb06 100644
    --- a/programs/zstdgrep.1
    +++ b/programs/zstdgrep.1
    @@ -1,5 +1,5 @@
     .
    -.TH "ZSTDGREP" "1" "February 2020" "zstd 1.4.5" "User Commands"
    +.TH "ZSTDGREP" "1" "May 2020" "zstd 1.4.5" "User Commands"
     .
     .SH "NAME"
     \fBzstdgrep\fR \- print lines matching a pattern in zstandard\-compressed files
    diff --git a/programs/zstdless.1 b/programs/zstdless.1
    index b06a4bc18fd..d54c6400cee 100644
    --- a/programs/zstdless.1
    +++ b/programs/zstdless.1
    @@ -1,5 +1,5 @@
     .
    -.TH "ZSTDLESS" "1" "February 2020" "zstd 1.4.5" "User Commands"
    +.TH "ZSTDLESS" "1" "May 2020" "zstd 1.4.5" "User Commands"
     .
     .SH "NAME"
     \fBzstdless\fR \- view zstandard\-compressed files
    
    From 608075abb29e2c3fa37c61cbfaaec8ade8a79ed3 Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Thu, 14 May 2020 17:06:39 -0700
    Subject: [PATCH 385/402] [test][regression] Update results.csv
    
    ---
     tests/regression/results.csv | 22 +++++++++++-----------
     1 file changed, 11 insertions(+), 11 deletions(-)
    
    diff --git a/tests/regression/results.csv b/tests/regression/results.csv
    index a0e1566a5d5..4db42a4889a 100644
    --- a/tests/regression/results.csv
    +++ b/tests/regression/results.csv
    @@ -33,7 +33,7 @@ silesia,                            level 19,                           compress
     silesia,                            long distance mode,                 compress cctx,                      4849491
     silesia,                            multithreaded,                      compress cctx,                      4849491
     silesia,                            multithreaded long distance mode,   compress cctx,                      4849491
    -silesia,                            small window log,                   compress cctx,                      7112472
    +silesia,                            small window log,                   compress cctx,                      7078156
     silesia,                            small hash log,                     compress cctx,                      6554898
     silesia,                            small chain log,                    compress cctx,                      4931093
     silesia,                            explicit params,                    compress cctx,                      4794609
    @@ -97,7 +97,7 @@ silesia,                            level 19,                           zstdcli,
     silesia,                            long distance mode,                 zstdcli,                            4839698
     silesia,                            multithreaded,                      zstdcli,                            4849539
     silesia,                            multithreaded long distance mode,   zstdcli,                            4839698
    -silesia,                            small window log,                   zstdcli,                            7123580
    +silesia,                            small window log,                   zstdcli,                            7104616
     silesia,                            small hash log,                     zstdcli,                            6554946
     silesia,                            small chain log,                    zstdcli,                            4931141
     silesia,                            explicit params,                    zstdcli,                            4797048
    @@ -123,7 +123,7 @@ silesia.tar,                        no source size,                     zstdcli,
     silesia.tar,                        long distance mode,                 zstdcli,                            4853140
     silesia.tar,                        multithreaded,                      zstdcli,                            4861462
     silesia.tar,                        multithreaded long distance mode,   zstdcli,                            4853140
    -silesia.tar,                        small window log,                   zstdcli,                            7127589
    +silesia.tar,                        small window log,                   zstdcli,                            7095284
     silesia.tar,                        small hash log,                     zstdcli,                            6587841
     silesia.tar,                        small chain log,                    zstdcli,                            4943269
     silesia.tar,                        explicit params,                    zstdcli,                            4822318
    @@ -188,7 +188,7 @@ silesia,                            no source size,                     advanced
     silesia,                            long distance mode,                 advanced one pass,                  4839650
     silesia,                            multithreaded,                      advanced one pass,                  4849491
     silesia,                            multithreaded long distance mode,   advanced one pass,                  4839650
    -silesia,                            small window log,                   advanced one pass,                  7123532
    +silesia,                            small window log,                   advanced one pass,                  7089646
     silesia,                            small hash log,                     advanced one pass,                  6554898
     silesia,                            small chain log,                    advanced one pass,                  4931093
     silesia,                            explicit params,                    advanced one pass,                  4797035
    @@ -214,7 +214,7 @@ silesia.tar,                        no source size,                     advanced
     silesia.tar,                        long distance mode,                 advanced one pass,                  4848046
     silesia.tar,                        multithreaded,                      advanced one pass,                  4860726
     silesia.tar,                        multithreaded long distance mode,   advanced one pass,                  4847343
    -silesia.tar,                        small window log,                   advanced one pass,                  7127549
    +silesia.tar,                        small window log,                   advanced one pass,                  7095237
     silesia.tar,                        small hash log,                     advanced one pass,                  6587833
     silesia.tar,                        small chain log,                    advanced one pass,                  4943266
     silesia.tar,                        explicit params,                    advanced one pass,                  4808543
    @@ -280,7 +280,7 @@ silesia,                            no source size,                     advanced
     silesia,                            long distance mode,                 advanced one pass small out,        4839650
     silesia,                            multithreaded,                      advanced one pass small out,        4849491
     silesia,                            multithreaded long distance mode,   advanced one pass small out,        4839650
    -silesia,                            small window log,                   advanced one pass small out,        7123532
    +silesia,                            small window log,                   advanced one pass small out,        7089646
     silesia,                            small hash log,                     advanced one pass small out,        6554898
     silesia,                            small chain log,                    advanced one pass small out,        4931093
     silesia,                            explicit params,                    advanced one pass small out,        4797035
    @@ -306,7 +306,7 @@ silesia.tar,                        no source size,                     advanced
     silesia.tar,                        long distance mode,                 advanced one pass small out,        4848046
     silesia.tar,                        multithreaded,                      advanced one pass small out,        4860726
     silesia.tar,                        multithreaded long distance mode,   advanced one pass small out,        4847343
    -silesia.tar,                        small window log,                   advanced one pass small out,        7127549
    +silesia.tar,                        small window log,                   advanced one pass small out,        7095237
     silesia.tar,                        small hash log,                     advanced one pass small out,        6587833
     silesia.tar,                        small chain log,                    advanced one pass small out,        4943266
     silesia.tar,                        explicit params,                    advanced one pass small out,        4808543
    @@ -372,7 +372,7 @@ silesia,                            no source size,                     advanced
     silesia,                            long distance mode,                 advanced streaming,                 4839650
     silesia,                            multithreaded,                      advanced streaming,                 4849491
     silesia,                            multithreaded long distance mode,   advanced streaming,                 4839650
    -silesia,                            small window log,                   advanced streaming,                 7123534
    +silesia,                            small window log,                   advanced streaming,                 7105714
     silesia,                            small hash log,                     advanced streaming,                 6554898
     silesia,                            small chain log,                    advanced streaming,                 4931093
     silesia,                            explicit params,                    advanced streaming,                 4797048
    @@ -398,7 +398,7 @@ silesia.tar,                        no source size,                     advanced
     silesia.tar,                        long distance mode,                 advanced streaming,                 4848046
     silesia.tar,                        multithreaded,                      advanced streaming,                 4861458
     silesia.tar,                        multithreaded long distance mode,   advanced streaming,                 4853136
    -silesia.tar,                        small window log,                   advanced streaming,                 7127549
    +silesia.tar,                        small window log,                   advanced streaming,                 7112148
     silesia.tar,                        small hash log,                     advanced streaming,                 6587834
     silesia.tar,                        small chain log,                    advanced streaming,                 4943271
     silesia.tar,                        explicit params,                    advanced streaming,                 4808570
    @@ -532,7 +532,7 @@ silesia,                            no source size,                     old stre
     silesia,                            long distance mode,                 old streaming advanced,             4849491
     silesia,                            multithreaded,                      old streaming advanced,             4849491
     silesia,                            multithreaded long distance mode,   old streaming advanced,             4849491
    -silesia,                            small window log,                   old streaming advanced,             7123534
    +silesia,                            small window log,                   old streaming advanced,             7105714
     silesia,                            small hash log,                     old streaming advanced,             6554898
     silesia,                            small chain log,                    old streaming advanced,             4931093
     silesia,                            explicit params,                    old streaming advanced,             4797048
    @@ -558,7 +558,7 @@ silesia.tar,                        no source size,                     old stre
     silesia.tar,                        long distance mode,                 old streaming advanced,             4861376
     silesia.tar,                        multithreaded,                      old streaming advanced,             4861376
     silesia.tar,                        multithreaded long distance mode,   old streaming advanced,             4861376
    -silesia.tar,                        small window log,                   old streaming advanced,             7127552
    +silesia.tar,                        small window log,                   old streaming advanced,             7112151
     silesia.tar,                        small hash log,                     old streaming advanced,             6587834
     silesia.tar,                        small chain log,                    old streaming advanced,             4943271
     silesia.tar,                        explicit params,                    old streaming advanced,             4808570
    
    From 255e5e3f562a8d8b551d900856670227d952e847 Mon Sep 17 00:00:00 2001
    From: Bimba Shrestha 
    Date: Fri, 15 May 2020 15:33:31 -0500
    Subject: [PATCH 386/402] [fuzz] Adding dictionary_stream_round_trip fuzzer
     (#2140)
    
    * Adding dictionary_stream_round_trip
    
    * fixing memory leak
    ---
     tests/fuzz/Makefile                       |   6 +-
     tests/fuzz/dictionary_stream_round_trip.c | 206 ++++++++++++++++++++++
     tests/fuzz/fuzz.py                        |   1 +
     3 files changed, 212 insertions(+), 1 deletion(-)
     create mode 100644 tests/fuzz/dictionary_stream_round_trip.c
    
    diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile
    index d71c34d6863..1af3dc73419 100644
    --- a/tests/fuzz/Makefile
    +++ b/tests/fuzz/Makefile
    @@ -94,7 +94,8 @@ FUZZ_TARGETS :=       \
     	zstd_frame_info \
     	simple_compress \
     	dictionary_loader \
    -	raw_dictionary_round_trip
    +	raw_dictionary_round_trip \
    +	dictionary_stream_round_trip
     
     all: $(FUZZ_TARGETS)
     
    @@ -164,6 +165,9 @@ dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary
     raw_dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o
     	$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_raw_dictionary_round_trip.o $(LIB_FUZZING_ENGINE) -o $@
     
    +dictionary_stream_round_trip: $(FUZZ_HEADERS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_stream_round_trip.o
    +	$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_ROUND_TRIP_OBJ) rt_fuzz_dictionary_stream_round_trip.o $(LIB_FUZZING_ENGINE) -o $@
    +
     dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o
     	$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_DECOMPRESS_OBJ) d_fuzz_dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@
     
    diff --git a/tests/fuzz/dictionary_stream_round_trip.c b/tests/fuzz/dictionary_stream_round_trip.c
    new file mode 100644
    index 00000000000..67e8c69ef0a
    --- /dev/null
    +++ b/tests/fuzz/dictionary_stream_round_trip.c
    @@ -0,0 +1,206 @@
    +/*
    + * Copyright (c) 2016-2020, Facebook, Inc.
    + * All rights reserved.
    + *
    + * This source code is licensed under both the BSD-style license (found in the
    + * LICENSE file in the root directory of this source tree) and the GPLv2 (found
    + * in the COPYING file in the root directory of this source tree).
    + * You may select, at your option, one of the above-listed licenses.
    + */
    +
    +/**
    + * This fuzz target performs a zstd round-trip test (compress & decompress),
    + * compares the result with the original, and calls abort() on corruption.
    + */
    +
    +#define ZSTD_STATIC_LINKING_ONLY
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include "fuzz_helpers.h"
    +#include "zstd_helpers.h"
    +#include "fuzz_data_producer.h"
    +
    +ZSTD_CCtx *cctx = NULL;
    +static ZSTD_DCtx *dctx = NULL;
    +static uint8_t* cBuf = NULL;
    +static uint8_t* rBuf = NULL;
    +static size_t bufSize = 0;
    +
    +static ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity,
    +                                    FUZZ_dataProducer_t *producer)
    +{
    +    ZSTD_outBuffer buffer = { dst, 0, 0 };
    +
    +    FUZZ_ASSERT(capacity > 0);
    +    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, capacity));
    +    FUZZ_ASSERT(buffer.size <= capacity);
    +
    +    return buffer;
    +}
    +
    +static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,
    +                                  FUZZ_dataProducer_t *producer)
    +{
    +    ZSTD_inBuffer buffer = { *src, 0, 0 };
    +
    +    FUZZ_ASSERT(*size > 0);
    +    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 1, *size));
    +    FUZZ_ASSERT(buffer.size <= *size);
    +    *src += buffer.size;
    +    *size -= buffer.size;
    +
    +    return buffer;
    +}
    +
    +static size_t compress(uint8_t *dst, size_t capacity,
    +                        const uint8_t *src, size_t srcSize,
    +                        const uint8_t* dict, size_t dictSize,
    +                        FUZZ_dataProducer_t *producer, int refPrefix,
    +                        ZSTD_dictContentType_e dictContentType)
    +{
    +    size_t dstSize = 0;
    +    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
    +    FUZZ_setRandomParameters(cctx, srcSize, producer);
    +
    +    /* Disable checksum so we can use sizes smaller than compress bound. */
    +    FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));
    +    if (refPrefix)
    +        FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(
    +            cctx, dict, dictSize,
    +            dictContentType));
    +    else
    +        FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
    +            cctx, dict, dictSize,
    +            (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
    +            dictContentType));
    +
    +    while (srcSize > 0) {
    +        ZSTD_inBuffer in = makeInBuffer(&src, &srcSize, producer);
    +        /* Mode controls the action. If mode == -1 we pick a new mode */
    +        int mode = -1;
    +        while (in.pos < in.size || mode != -1) {
    +            ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);
    +            /* Previous action finished, pick a new mode. */
    +            if (mode == -1) mode = FUZZ_dataProducer_uint32Range(producer, 0, 9);
    +            switch (mode) {
    +                case 0: /* fall-through */
    +                case 1: /* fall-through */
    +                case 2: {
    +                    size_t const ret =
    +                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush);
    +                    FUZZ_ZASSERT(ret);
    +                    if (ret == 0)
    +                        mode = -1;
    +                    break;
    +                }
    +                case 3: {
    +                    size_t ret =
    +                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
    +                    FUZZ_ZASSERT(ret);
    +                    /* Reset the compressor when the frame is finished */
    +                    if (ret == 0) {
    +                        ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
    +                        if (FUZZ_dataProducer_uint32Range(producer, 0, 7) == 0) {
    +                            size_t const remaining = in.size - in.pos;
    +                            FUZZ_setRandomParameters(cctx, remaining, producer);
    +                        }
    +                        mode = -1;
    +                    }
    +                    break;
    +                }
    +                case 4: {
    +                    ZSTD_inBuffer nullIn = { NULL, 0, 0 };
    +                    ZSTD_outBuffer nullOut = { NULL, 0, 0 };
    +                    size_t const ret = ZSTD_compressStream2(cctx, &nullOut, &nullIn, ZSTD_e_continue);
    +                    FUZZ_ZASSERT(ret);
    +                }
    +                /* fall-through */
    +                default: {
    +                    size_t const ret =
    +                        ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_continue);
    +                    FUZZ_ZASSERT(ret);
    +                    mode = -1;
    +                }
    +            }
    +            dst += out.pos;
    +            dstSize += out.pos;
    +            capacity -= out.pos;
    +        }
    +    }
    +    for (;;) {
    +        ZSTD_inBuffer in = {NULL, 0, 0};
    +        ZSTD_outBuffer out = makeOutBuffer(dst, capacity, producer);
    +        size_t const ret = ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end);
    +        FUZZ_ZASSERT(ret);
    +
    +        dst += out.pos;
    +        dstSize += out.pos;
    +        capacity -= out.pos;
    +        if (ret == 0)
    +            break;
    +    }
    +    return dstSize;
    +}
    +
    +int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
    +{
    +    size_t neededBufSize;
    +
    +    /* Give a random portion of src data to the producer, to use for
    +    parameter generation. The rest will be used for (de)compression */
    +    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
    +    size = FUZZ_dataProducer_reserveDataPrefix(producer);
    +
    +    neededBufSize = ZSTD_compressBound(size) * 15;
    +
    +    /* Allocate all buffers and contexts if not already allocated */
    +    if (neededBufSize > bufSize) {
    +        free(cBuf);
    +        free(rBuf);
    +        cBuf = (uint8_t*)FUZZ_malloc(neededBufSize);
    +        rBuf = (uint8_t*)FUZZ_malloc(neededBufSize);
    +        bufSize = neededBufSize;
    +    }
    +    if (!cctx) {
    +        cctx = ZSTD_createCCtx();
    +        FUZZ_ASSERT(cctx);
    +    }
    +    if (!dctx) {
    +        dctx = ZSTD_createDCtx();
    +        FUZZ_ASSERT(dctx);
    +    }
    +
    +    {
    +        ZSTD_dictContentType_e dictContentType = FUZZ_dataProducer_uint32Range(producer, 0, 2);
    +        FUZZ_dict_t dict = FUZZ_train(src, size, producer);
    +        int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;
    +
    +        size_t const cSize = compress(cBuf, neededBufSize, src, size, dict.buff, dict.size, producer, refPrefix, dictContentType);
    +
    +        if (refPrefix)
    +            FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(
    +                dctx, dict.buff, dict.size,
    +                dictContentType));
    +        else
    +            FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
    +                dctx, dict.buff, dict.size,
    +                (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
    +                dictContentType));
    +        size_t const rSize =
    +            ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize);
    +        FUZZ_ZASSERT(rSize);
    +        FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
    +        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
    +        free(dict.buff);
    +    }
    +
    +    FUZZ_dataProducer_free(producer);
    +#ifndef STATEFUL_FUZZING
    +    ZSTD_freeCCtx(cctx); cctx = NULL;
    +    ZSTD_freeDCtx(dctx); dctx = NULL;
    +#endif
    +    return 0;
    +}
    diff --git a/tests/fuzz/fuzz.py b/tests/fuzz/fuzz.py
    index 29d26955733..6875d1d6036 100755
    --- a/tests/fuzz/fuzz.py
    +++ b/tests/fuzz/fuzz.py
    @@ -58,6 +58,7 @@ def __init__(self, input_type, frame_type=FrameType.ZSTD):
         'simple_compress': TargetInfo(InputType.RAW_DATA),
         'dictionary_loader': TargetInfo(InputType.DICTIONARY_DATA),
         'raw_dictionary_round_trip': TargetInfo(InputType.RAW_DATA),
    +    'dictionary_stream_round_trip': TargetInfo(InputType.RAW_DATA),
     }
     TARGETS = list(TARGET_INFO.keys())
     ALL_TARGETS = TARGETS + ['all']
    
    From 18082ce85a55f3e8199afafac31400a62d15aca6 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Fri, 15 May 2020 17:19:00 -0700
    Subject: [PATCH 387/402] updated CHANGELOG for v1.4.5
    
    ---
     CHANGELOG | 27 ++++++++++++++++++++++-----
     1 file changed, 22 insertions(+), 5 deletions(-)
    
    diff --git a/CHANGELOG b/CHANGELOG
    index 5e78e38b9e2..0ed939a5bbb 100644
    --- a/CHANGELOG
    +++ b/CHANGELOG
    @@ -1,11 +1,28 @@
     v1.4.5
     fix : Compression ratio regression on huge files (> 3 GB) using high levels (--ultra) and multithreading, by @terrelln
    -perf: Improved decompression speed: x64 : +10% (clang) / +5% (gcc); ARM : from +15% to +50%, depending on chip, by @terrelln
    -cli: new command --filelist=FILE : provide list of files within a file, by @AhmedAbdellah19
    -cli: new command --patch-from=FILE (experimental) : generate diff from 2 files, by @bimbashrestha
    -api: controlled block size for lower latency, new experimental parameter by @ephiepark
    -build: mingw cross-compilation from unix, by @Ericson2314
    +perf: Improved decompression speed: x64 : +10% (clang) / +5% (gcc); ARM : from +15% to +50%, depending on SoC, by @terrelln
    +perf: Automatically downsizes ZSTD_DCtx when too large for too long (#2069, by @bimbashreshta)
    +perf: Improved fast compression speed on aarch64 (#2040, ~+3%, by @caoyzh)
    +perf: Small level 1 compression speed gains (depending on compiler)
    +cli : New --patch-from command, create and apply patches from files, by @bimbashreshta
    +cli : New --filelist= : Provide a list of files to operate upon from a file
    +cli : -b -d command can now benchmark decompression on multiple files
    +cli : New --no-content-size command
    +cli : New --show-default-cparams information command
    +api : ZDICT_finalizeDictionary() is promoted to stable (#2111)
    +api : new experimental parameter ZSTD_d_stableOutBuffer (#2094)
    +build: Generate a single-file libzstd library (#2065, by @cwoffenden)
    +build: Relative includes no longer require -I compiler flags for zstd lib subdirs (#2103, by @felixhandte)
    +build: zstd now compiles cleanly under -pedantic (#2099)
    +build: zstd now compiles with make-4.3
    +build: Support mingw cross-compilation from Linux, by @Ericson2314
    +build: Meson multi-thread build fix on windows
    +build: Some misc icc fixes backed by new ci test on travis
     misc: bitflip analyzer tool, by @felixhandte
    +misc: Extend largeNbDicts benchmark to compression
    +misc: Edit-distance match finder in contrib/
    +doc : Improved beginner CONTRIBUTING.md docs
    +doc : New issue templates for zstd
     
     v1.4.4
     perf: Improved decompression speed, by > 10%, by @terrelln
    
    From c6b03fa69c3944bf6240195ade2c3a89676eea57 Mon Sep 17 00:00:00 2001
    From: Carl Woffenden 
    Date: Mon, 18 May 2020 10:12:02 +0200
    Subject: [PATCH 388/402] Reduced generated sized on macOS (and other envs
     where realpath is missing)
    
    Added Python fallback for when realpath fails.
    ---
     contrib/single_file_libs/combine.sh | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/contrib/single_file_libs/combine.sh b/contrib/single_file_libs/combine.sh
    index 05c7bce8e5c..8eac4f9eb14 100755
    --- a/contrib/single_file_libs/combine.sh
    +++ b/contrib/single_file_libs/combine.sh
    @@ -93,6 +93,12 @@ resolve_include() {
             echo "$relpath"
             return 0
           fi
    +      # Fallback on Python to reduce the path if the above fails.
    +      local relpath=$(python -c "import os,sys; print os.path.relpath(sys.argv[1])" "$root/$inc" 2>/dev/null)
    +      if [ "$relpath" != "" ]; then # not all distros have realpath...
    +        echo "$relpath"
    +        return 0
    +      fi
           # Worst case, fall back to just the root + relative include path. The
           # problem with this is that it is possible to emit multiple different
           # resolved paths to the same file, depending on exactly how its included.
    
    From 1a8767cbda7dbf5087d87af3bf773330841f9b6b Mon Sep 17 00:00:00 2001
    From: Carl Woffenden 
    Date: Mon, 18 May 2020 12:33:44 +0200
    Subject: [PATCH 389/402] Minor tidy
    
    ---
     contrib/single_file_libs/README.md                     | 6 +++---
     contrib/single_file_libs/create_single_file_library.sh | 2 +-
     contrib/single_file_libs/zstd-in.c                     | 2 +-
     3 files changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/contrib/single_file_libs/README.md b/contrib/single_file_libs/README.md
    index b8a44a3ecb7..d88e8fc6bda 100644
    --- a/contrib/single_file_libs/README.md
    +++ b/contrib/single_file_libs/README.md
    @@ -12,7 +12,7 @@ This is the most common use case. The decompression library is small, adding, fo
     Create `zstddeclib.c` from the Zstd source using:
     ```
     cd zstd/contrib/single_file_libs
    -./combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c
    +./combine.sh -r ../../lib -o zstddeclib.c zstddeclib-in.c
     ```
     Then add the resulting file to your project (see the [example files](examples)).
     
    @@ -21,12 +21,12 @@ Then add the resulting file to your project (see the [example files](examples)).
     Full Library
     ------------
     
    -The same tool can amalgamate the entire Zstd library for ease of adding both compression and decompression to a project. The [roundtrip example](examples/roundtrip.c) uses the original `zstd.h` with the remaining source files combined into `zstd.c` (currently just over 1MB) created from `zstd-in.c`. As with the standalone decoder the most useful compile flags have already been rolled-in and the resulting file can be added to a project as-is.
    +The same tool can amalgamate the entire Zstd library for ease of adding both compression and decompression to a project. The [roundtrip example](examples/roundtrip.c) uses the original `zstd.h` with the remaining source files combined into `zstd.c` (currently just over 1.2MB) created from `zstd-in.c`. As with the standalone decoder the most useful compile flags have already been rolled-in and the resulting file can be added to a project as-is.
     
     Create `zstd.c` from the Zstd source using:
     ```
     cd zstd/contrib/single_file_libs
    -combine.sh -r ../../lib -r ../../lib/common -r ../../lib/compress -r ../../lib/decompress -k zstd.h -o zstd.c zstd-in.c
    +./combine.sh -r ../../lib -o zstd.c zstd-in.c
     ```
     It's possible to create a compressor-only library but since the decompressor is so small in comparison this doesn't bring much of a gain (but for the curious, simply remove the files in the _decompress_ section at the end of `zstd-in.c`).
     
    diff --git a/contrib/single_file_libs/create_single_file_library.sh b/contrib/single_file_libs/create_single_file_library.sh
    index 6cbff459577..6f38526d5bf 100755
    --- a/contrib/single_file_libs/create_single_file_library.sh
    +++ b/contrib/single_file_libs/create_single_file_library.sh
    @@ -5,7 +5,7 @@ ZSTD_SRC_ROOT="../../lib"
     
     # Amalgamate the sources
     echo "Amalgamating files... this can take a while"
    -./combine.sh -r "$ZSTD_SRC_ROOT" -k zstd.h -o zstd.c zstd-in.c
    +./combine.sh -r "$ZSTD_SRC_ROOT" -o zstd.c zstd-in.c
     # Did combining work?
     if [ $? -ne 0 ]; then
       echo "Combine script: FAILED"
    diff --git a/contrib/single_file_libs/zstd-in.c b/contrib/single_file_libs/zstd-in.c
    index aa197a682c0..cac8055491d 100644
    --- a/contrib/single_file_libs/zstd-in.c
    +++ b/contrib/single_file_libs/zstd-in.c
    @@ -4,7 +4,7 @@
      *
      * Generate using:
      * \code
    - *	combine.sh -r ../../lib -k zstd.h -o zstd.c zstd-in.c
    + *	combine.sh -r ../../lib -o zstd.c zstd-in.c
      * \endcode
      */
     /*
    
    From d37fcf36eb2feff6234684f97ef41296a232a6f0 Mon Sep 17 00:00:00 2001
    From: "W. Felix Handte" 
    Date: Mon, 18 May 2020 14:54:06 -0400
    Subject: [PATCH 390/402] Don't Use `[[` in Shell Scripts
    
    ---
     tests/playTests.sh | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tests/playTests.sh b/tests/playTests.sh
    index 3c91b958f18..4ccf4bd24d9 100755
    --- a/tests/playTests.sh
    +++ b/tests/playTests.sh
    @@ -267,7 +267,7 @@ test ! -f precompressedFilterTestDir/input.5.zst.zst
     test ! -f precompressedFilterTestDir/input.6.zst.zst
     file1timestamp=`$MTIME precompressedFilterTestDir/input.5.zst`
     file2timestamp=`$MTIME precompressedFilterTestDir/input.7.zst`
    -if [[ $file2timestamp -ge $file1timestamp ]]; then
    +if [ $file2timestamp -ge $file1timestamp ]; then
       println "Test is successful. input.5.zst is precompressed and therefore not compressed/modified again."
     else
       println "Test is not successful"
    
    From b2092c6dc41b27dcc0b66bb470ff4371c6010c13 Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Mon, 18 May 2020 12:35:44 -0700
    Subject: [PATCH 391/402] [ldm] Reset loadedDictEnd when the context is reset
    
    ---
     lib/compress/zstd_compress.c   |  1 +
     lib/compress/zstd_ldm.c        |  8 ++++++++
     lib/compress/zstdmt_compress.c | 15 +++++++++++----
     3 files changed, 20 insertions(+), 4 deletions(-)
    
    diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c
    index 2cfa93051fd..3f963b1cfff 100644
    --- a/lib/compress/zstd_compress.c
    +++ b/lib/compress/zstd_compress.c
    @@ -1576,6 +1576,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
     
                 ZSTD_window_init(&zc->ldmState.window);
                 ZSTD_window_clear(&zc->ldmState.window);
    +            zc->ldmState.loadedDictEnd = 0;
             }
     
             DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
    diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
    index 22f3628070a..869986a0af2 100644
    --- a/lib/compress/zstd_ldm.c
    +++ b/lib/compress/zstd_ldm.c
    @@ -463,6 +463,8 @@ size_t ZSTD_ldm_generateSequences(
                 U32 const correction = ZSTD_window_correctOverflow(
                     &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
                 ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);
    +            /* invalidate dictionaries on overflow correction */
    +            ldmState->loadedDictEnd = 0;
             }
             /* 2. We enforce the maximum offset allowed.
              *
    @@ -471,6 +473,12 @@ size_t ZSTD_ldm_generateSequences(
              * TODO: * Test the chunk size.
              *       * Try invalidation after the sequence generation and test the
              *         the offset against maxDist directly.
    +         *
    +         * NOTE: Because of dictionaries + sequence splitting we MUST make sure
    +         * that any offset used is valid at the END of the sequence, since it may
    +         * be split into two sequences. This condition holds when using
    +         * ZSTD_window_enforceMaxDist(), but if we move to checking offsets
    +         * against maxDist directly, we'll have to carefully handle that case.
              */
             ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, &ldmState->loadedDictEnd, NULL);
             /* 3. Generate the sequences for the chunk, and get newLeftoverSize. */
    diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
    index f6b26a757fa..77a137bdf9c 100644
    --- a/lib/compress/zstdmt_compress.c
    +++ b/lib/compress/zstdmt_compress.c
    @@ -493,7 +493,6 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState,
             ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
             /* Reset the window */
             ZSTD_window_init(&serialState->ldmState.window);
    -        serialState->ldmWindow = serialState->ldmState.window;
             /* Resize tables and output space if necessary. */
             if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
                 ZSTD_free(serialState->ldmState.hashTable, cMem);
    @@ -508,12 +507,20 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState,
             /* Zero the tables */
             memset(serialState->ldmState.hashTable, 0, hashSize);
             memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
    +
    +        /* Update window state and fill hash table with dict */
    +        if (dictSize > 0) {
    +            BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
    +            ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
    +            ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
    +            serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
    +        }
    +
    +        /* Initialize serialState's copy of ldmWindow. */
    +        serialState->ldmWindow = serialState->ldmState.window;
         }
     
    -    /* Update window state and fill hash table with dict */
         if (params.ldmParams.enableLdm && dict) {
    -        ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
    -        ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, (const BYTE*)dict + dictSize, ¶ms.ldmParams);
         }
     
         serialState->params = params;
    
    From 87dbd6d4bf0c441accc5323f084b968aacb345bd Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Mon, 18 May 2020 12:56:34 -0700
    Subject: [PATCH 392/402] [test] Improve LDM forceMaxWindow test
    
    ---
     tests/fuzzer.c | 21 +++++++++++++++------
     1 file changed, 15 insertions(+), 6 deletions(-)
    
    diff --git a/tests/fuzzer.c b/tests/fuzzer.c
    index bbbcb31addc..e7f51430197 100644
    --- a/tests/fuzzer.c
    +++ b/tests/fuzzer.c
    @@ -631,17 +631,26 @@ static int basicUnitTests(U32 const seed, double compressibility)
         DISPLAYLEVEL(3, "test%3i : testing dict compression with enableLdm and forceMaxWindow : ", testNb++);
         {
             ZSTD_CCtx* const cctx = ZSTD_createCCtx();
    +        ZSTD_DCtx* const dctx = ZSTD_createDCtx();
             void* dict = (void*)malloc(CNBuffSize);
    +        int nbWorkers;
     
    -        RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed);
    -        RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed);
    +        for (nbWorkers = 0; nbWorkers < 3; ++nbWorkers) {
    +            RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed);
    +            RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed);
     
    -        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1));
    -        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
    -        assert(!ZSTD_isError(ZSTD_compress_usingDict(cctx, compressedBuffer, compressedBufferSize,
    -            CNBuffer, CNBuffSize, dict, CNBuffSize, 3)));
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, ZSTD_c_nbWorkers));
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1));
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
    +            CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, CNBuffSize));
    +            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
    +            CHECK_Z(cSize);
    +            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, CNBuffSize));
    +        }
     
             ZSTD_freeCCtx(cctx);
    +        ZSTD_freeDCtx(dctx);
             free(dict);
         }
         DISPLAYLEVEL(3, "OK \n");
    
    From 7b317b4876ebd86bd1f1ad679c20f9bdf4d426b4 Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Mon, 18 May 2020 15:11:02 -0700
    Subject: [PATCH 393/402] [test] Test that the ldm dictionary gets invalidated
     on reset
    
    ---
     tests/fuzzer.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 51 insertions(+)
    
    diff --git a/tests/fuzzer.c b/tests/fuzzer.c
    index e7f51430197..49ea53f7fb5 100644
    --- a/tests/fuzzer.c
    +++ b/tests/fuzzer.c
    @@ -655,6 +655,57 @@ static int basicUnitTests(U32 const seed, double compressibility)
         }
         DISPLAYLEVEL(3, "OK \n");
     
    +    DISPLAYLEVEL(3, "test%3i : testing ldm dictionary gets invalidated : ", testNb++);
    +    {
    +        ZSTD_CCtx* const cctx = ZSTD_createCCtx();
    +        ZSTD_DCtx* const dctx = ZSTD_createDCtx();
    +        void* dict = (void*)malloc(CNBuffSize);
    +        size_t const kWindowLog = 10;
    +        size_t const kWindowSize = (size_t)1 << kWindowLog;
    +        size_t const dictSize = kWindowSize * 10;
    +        size_t const srcSize1 = kWindowSize / 2;
    +        size_t const srcSize2 = kWindowSize * 10;
    +        int nbWorkers;
    +
    +        if (CNBuffSize < dictSize) goto _output_error;
    +
    +        RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed);
    +        RDG_genBuffer(CNBuffer, srcSize1 + srcSize2, 0.5, 0.5, seed);
    +
    +        /* Enable checksum to verify round trip. */
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
    +        /* Disable content size to skip single-pass decompression. */
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)kWindowLog));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmMinMatch, 32));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 1));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 12));
    +
    +        for (nbWorkers = 0; nbWorkers < 3; ++nbWorkers) {
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkers));
    +            /* Round trip once with a dictionary. */
    +            CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));
    +            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1);
    +            CHECK_Z(cSize);
    +            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
    +            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2);
    +            /* Streaming decompression to catch out of bounds offsets. */
    +            {
    +                ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
    +                ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};
    +                size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);
    +                CHECK_Z(dSize);
    +                if (dSize != 0) goto _output_error;
    +            }
    +        }
    +
    +        ZSTD_freeCCtx(cctx);
    +        ZSTD_freeDCtx(dctx);
    +        free(dict);
    +    }
    +    DISPLAYLEVEL(3, "OK \n");
    +
         /* Note: this test takes 0.5 seconds to run */
         DISPLAYLEVEL(3, "test%3i : testing refPrefx vs refPrefx + ldm (size comparison) : ", testNb++);
         {
    
    From fdc56baa4248e903f364bca46362713531d24748 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Mon, 18 May 2020 21:05:10 -0700
    Subject: [PATCH 394/402] fix 22294 (#2151)
    
    ---
     lib/compress/zstd_fast.c       |  3 ++-
     lib/compress/zstd_ldm.c        |  3 ++-
     lib/compress/zstdmt_compress.c | 31 +++++++++++++++++++++----------
     tests/fuzz/.gitignore          |  8 +++++++-
     4 files changed, 32 insertions(+), 13 deletions(-)
    
    diff --git a/lib/compress/zstd_fast.c b/lib/compress/zstd_fast.c
    index 9906e4ba287..85a3a7a91e4 100644
    --- a/lib/compress/zstd_fast.c
    +++ b/lib/compress/zstd_fast.c
    @@ -398,7 +398,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
         const BYTE* const ilimit = iend - 8;
         U32 offset_1=rep[0], offset_2=rep[1];
     
    -    DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic");
    +    DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)", offset_1);
     
         /* switch to "regular" variant if extDict is invalidated due to maxDistance */
         if (prefixStartIndex == dictStartIndex)
    @@ -415,6 +415,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
             const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
             const BYTE* const repMatch = repBase + repIndex;
             hashTable[h] = current;   /* update hash table */
    +        DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current);
             assert(offset_1 <= current +1);   /* check repIndex */
     
             if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex))
    diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c
    index 869986a0af2..8c479483581 100644
    --- a/lib/compress/zstd_ldm.c
    +++ b/lib/compress/zstd_ldm.c
    @@ -228,6 +228,7 @@ void ZSTD_ldm_fillHashTable(
                 ldmState_t* state, const BYTE* ip,
                 const BYTE* iend, ldmParams_t const* params)
     {
    +    DEBUGLOG(5, "ZSTD_ldm_fillHashTable");
         if ((size_t)(iend - ip) >= params->minMatchLength) {
             U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength);
             ZSTD_ldm_fillLdmHashTable(
    @@ -594,7 +595,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
             ZSTD_ldm_limitTableUpdate(ms, ip);
             ZSTD_ldm_fillFastTables(ms, ip);
             /* Run the block compressor */
    -        DEBUGLOG(5, "calling block compressor on segment of size %u", sequence.litLength);
    +        DEBUGLOG(5, "pos %u : calling block compressor on segment of size %u", (unsigned)(ip-istart), sequence.litLength);
             {
                 size_t const newLitLength =
                     blockCompressor(ms, seqStore, rep, ip, sequence.litLength);
    diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
    index 77a137bdf9c..5be7edfeb4b 100644
    --- a/lib/compress/zstdmt_compress.c
    +++ b/lib/compress/zstdmt_compress.c
    @@ -461,9 +461,13 @@ typedef struct {
         ZSTD_window_t ldmWindow;  /* A thread-safe copy of ldmState.window */
     } serialState_t;
     
    -static int ZSTDMT_serialState_reset(serialState_t* serialState, 
    -                        ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, 
    -                        size_t jobSize, const void* dict, size_t const dictSize)
    +static int
    +ZSTDMT_serialState_reset(serialState_t* serialState,
    +                         ZSTDMT_seqPool* seqPool,
    +                         ZSTD_CCtx_params params,
    +                         size_t jobSize,
    +                         const void* dict, size_t const dictSize,
    +                         ZSTD_dictContentType_e dictContentType)
     {
         /* Adjust parameters */
         if (params.ldmParams.enableLdm) {
    @@ -510,10 +514,14 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState,
     
             /* Update window state and fill hash table with dict */
             if (dictSize > 0) {
    -            BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
    -            ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
    -            ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
    -            serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
    +            if (dictContentType == ZSTD_dct_rawContent) {
    +                BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
    +                ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
    +                ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
    +                serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
    +            } else {
    +                /* don't even load anything */
    +            }
             }
     
             /* Initialize serialState's copy of ldmWindow. */
    @@ -1251,7 +1259,8 @@ ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nb
     /* ZSTDMT_compress_advanced_internal() :
      * This is a blocking function : it will only give back control to caller after finishing its compression job.
      */
    -static size_t ZSTDMT_compress_advanced_internal(
    +static size_t
    +ZSTDMT_compress_advanced_internal(
                     ZSTDMT_CCtx* mtctx,
                     void* dst, size_t dstCapacity,
               const void* src, size_t srcSize,
    @@ -1283,7 +1292,8 @@ static size_t ZSTDMT_compress_advanced_internal(
     
         assert(avgJobSize >= 256 KB);  /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
         ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
    -    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0))
    +    /* LDM doesn't even try to load the dictionary in single-ingestion mode */
    +    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto))
             return ERROR(memory_allocation);
     
         FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , "");  /* only expands if necessary */
    @@ -1516,7 +1526,8 @@ size_t ZSTDMT_initCStream_internal(
         mtctx->allJobsCompleted = 0;
         mtctx->consumed = 0;
         mtctx->produced = 0;
    -    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize, dict, dictSize))
    +    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize,
    +                                 dict, dictSize, dictContentType))
             return ERROR(memory_allocation);
         return 0;
     }
    diff --git a/tests/fuzz/.gitignore b/tests/fuzz/.gitignore
    index e2563097e74..b6fc6e50605 100644
    --- a/tests/fuzz/.gitignore
    +++ b/tests/fuzz/.gitignore
    @@ -5,10 +5,16 @@ block_round_trip
     dictionary_decompress
     dictionary_loader
     dictionary_round_trip
    +dictionary_stream_round_trip
    +raw_dictionary_round_trip
     simple_compress
     simple_decompress
     simple_round_trip
     stream_decompress
     stream_round_trip
     zstd_frame_info
    -fuzz-*.log
    \ No newline at end of file
    +fuzz-*.log
    +
    +# misc
    +trace
    +tmp*
    
    From b82bf711fc5d3daca00f0236a7c5961ed28dd46a Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Tue, 19 May 2020 11:42:53 -0700
    Subject: [PATCH 395/402] [fuzz] Expand the allowedExpansion
    
    ---
     tests/fuzz/simple_round_trip.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tests/fuzz/simple_round_trip.c b/tests/fuzz/simple_round_trip.c
    index 348da03a962..2f008d06a51 100644
    --- a/tests/fuzz/simple_round_trip.c
    +++ b/tests/fuzz/simple_round_trip.c
    @@ -60,7 +60,7 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
                     + 3 /* number of sequences */
                     + 1 /* symbol compression modes */;
                 size_t const expectedExpansion = bytesPerBlock * (1 + (normalCSize / MAX(1, targetCBlockSize)));
    -            size_t const allowedExpansion = (srcSize >> 4) + 3 * expectedExpansion + 10;
    +            size_t const allowedExpansion = (srcSize >> 3) + 5 * expectedExpansion + 10;
                 FUZZ_ASSERT(cSize <= normalCSize + allowedExpansion);
             }
         }
    
    From 3cc227e90e446f1d195f62038ae50d3e9aeadab2 Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Tue, 19 May 2020 15:55:03 -0700
    Subject: [PATCH 396/402] [ldm][mt] Fix loadedDictEnd
    
    ---
     lib/compress/zstdmt_compress.c | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c
    index 5be7edfeb4b..1e3c8fdbee2 100644
    --- a/lib/compress/zstdmt_compress.c
    +++ b/lib/compress/zstdmt_compress.c
    @@ -513,6 +513,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
             memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
     
             /* Update window state and fill hash table with dict */
    +        serialState->ldmState.loadedDictEnd = 0;
             if (dictSize > 0) {
                 if (dictContentType == ZSTD_dct_rawContent) {
                     BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
    @@ -528,9 +529,6 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
             serialState->ldmWindow = serialState->ldmState.window;
         }
     
    -    if (params.ldmParams.enableLdm && dict) {
    -    }
    -
         serialState->params = params;
         serialState->params.jobSize = (U32)jobSize;
         return 0;
    
    From 651d3d73e0878224923be30c8b9fe9f9b3e01b14 Mon Sep 17 00:00:00 2001
    From: Nick Terrell 
    Date: Tue, 19 May 2020 16:14:14 -0700
    Subject: [PATCH 397/402] [test] Update the ldm loadedDictEnd test to cover
     zstdmt
    
    ---
     tests/fuzzer.c | 62 ++++++++++++++++++++++++++++++++++----------------
     1 file changed, 43 insertions(+), 19 deletions(-)
    
    diff --git a/tests/fuzzer.c b/tests/fuzzer.c
    index 49ea53f7fb5..8ac2864f3e3 100644
    --- a/tests/fuzzer.c
    +++ b/tests/fuzzer.c
    @@ -639,7 +639,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
                 RDG_genBuffer(dict, CNBuffSize, 0.5, 0.5, seed);
                 RDG_genBuffer(CNBuffer, CNBuffSize, 0.6, 0.6, seed);
     
    -            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, ZSTD_c_nbWorkers));
    +            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkers));
                 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
                 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_forceMaxWindow, 1));
                 CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
    @@ -665,7 +665,6 @@ static int basicUnitTests(U32 const seed, double compressibility)
             size_t const dictSize = kWindowSize * 10;
             size_t const srcSize1 = kWindowSize / 2;
             size_t const srcSize2 = kWindowSize * 10;
    -        int nbWorkers;
     
             if (CNBuffSize < dictSize) goto _output_error;
     
    @@ -680,24 +679,49 @@ static int basicUnitTests(U32 const seed, double compressibility)
             CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, 1));
             CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmMinMatch, 32));
             CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 1));
    -        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 12));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 16));
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmBucketSizeLog, 3));
     
    -        for (nbWorkers = 0; nbWorkers < 3; ++nbWorkers) {
    -            CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, nbWorkers));
    -            /* Round trip once with a dictionary. */
    -            CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));
    -            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1);
    -            CHECK_Z(cSize);
    -            CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
    -            cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2);
    -            /* Streaming decompression to catch out of bounds offsets. */
    -            {
    -                ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
    -                ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};
    -                size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);
    -                CHECK_Z(dSize);
    -                if (dSize != 0) goto _output_error;
    -            }
    +        /* Round trip once with a dictionary. */
    +        CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));
    +        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1);
    +        CHECK_Z(cSize);
    +        CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
    +        cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2);
    +        /* Streaming decompression to catch out of bounds offsets. */
    +        {
    +            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
    +            ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};
    +            size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);
    +            CHECK_Z(dSize);
    +            if (dSize != 0) goto _output_error;
    +        }
    +
    +        CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2));
    +        /* Round trip once with a dictionary. */
    +        CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));
    +        {
    +            ZSTD_inBuffer in = {CNBuffer, srcSize1, 0};
    +            ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};
    +            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
    +            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
    +            cSize = out.pos;
    +        }
    +        CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
    +        {
    +            ZSTD_inBuffer in = {CNBuffer, srcSize2, 0};
    +            ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};
    +            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
    +            CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
    +            cSize = out.pos;
    +        }
    +        /* Streaming decompression to catch out of bounds offsets. */
    +        {
    +            ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
    +            ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};
    +            size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);
    +            CHECK_Z(dSize);
    +            if (dSize != 0) goto _output_error;
             }
     
             ZSTD_freeCCtx(cctx);
    
    From 14aaa5290a674b330f15a1bd154813c7d83794b5 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 21 May 2020 00:22:52 -0700
    Subject: [PATCH 398/402] fixed zbuff test
    
    error introduced in https://github.com/facebook/zstd/blame/3b39ce6b527c5cfe395a187c75b77baf5cc7de02/.travis.yml#L192
    ---
     .travis.yml                   |  2 +-
     build/meson/tests/meson.build | 15 ---------------
     2 files changed, 1 insertion(+), 16 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index 01baee399cb..ce69723d318 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -189,7 +189,7 @@ matrix:
         - name: zbuff test
           if: branch = master
           script:
    -        - make test-zbuff
    +        - make -C tests test-zbuff
     
         - name: Versions Compatibility Test   # 11.5mn
           if: branch = master
    diff --git a/build/meson/tests/meson.build b/build/meson/tests/meson.build
    index 6b1282def5f..728dba02d5a 100644
    --- a/build/meson/tests/meson.build
    +++ b/build/meson/tests/meson.build
    @@ -60,17 +60,6 @@ fuzzer = executable('fuzzer',
       dependencies: libzstd_dep,
       install: false)
     
    -zbufftest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
    -  join_paths(zstd_rootdir, 'programs/util.c'),
    -  join_paths(zstd_rootdir, 'programs/timefn.c'),
    -  join_paths(zstd_rootdir, 'tests/zbufftest.c')]
    -zbufftest = executable('zbufftest',
    -  zbufftest_sources,
    -  c_args: ['-Wno-deprecated-declarations'],
    -  include_directories: test_includes,
    -  dependencies: libzstd_dep,
    -  install: false)
    -
     zstreamtest_sources = [join_paths(zstd_rootdir, 'programs/datagen.c'),
       join_paths(zstd_rootdir, 'programs/util.c'),
       join_paths(zstd_rootdir, 'programs/timefn.c'),
    @@ -193,10 +182,6 @@ if use_zlib
         timeout: 480)
     endif
     
    -test('test-zbuff',
    -  zbufftest,
    -  args: [ZSTREAM_TESTTIME],
    -  timeout: 120)
     test('test-zstream-1',
       zstreamtest,
       args: ['-v', ZSTREAM_TESTTIME] + FUZZER_FLAGS,
    
    From ad0c0d19468248e638843fc7611ce09db156aa0b Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Wed, 20 May 2020 22:56:25 -0700
    Subject: [PATCH 399/402] fixed appveyor long tests
    
    playTests changed variable name
    ---
     appveyor.yml | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/appveyor.yml b/appveyor.yml
    index fdc87376c8c..d09a136aeb0 100644
    --- a/appveyor.yml
    +++ b/appveyor.yml
    @@ -169,7 +169,8 @@
       - SET "FUZZERTEST=-T30s"
       - if [%HOST%]==[visual] if [%CONFIGURATION%]==[Release] (
           CD tests &&
    -      SET ZSTD=./zstd.exe &&
    +      SET ZSTD_BIN=zstd.exe &&
    +      SET DATAGEN_BIN=datagen.exe &&
           sh -e playTests.sh --test-large-data &&
           fullbench.exe -i1 &&
           fullbench.exe -i1 -P0 &&
    
    From a63810e2ac95d3a969a8e6c1a56705bc68206d6d Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 21 May 2020 10:26:40 -0700
    Subject: [PATCH 400/402] try to fix PPC64 Qemu tests
    
    ---
     .travis.yml | 13 +++++++------
     1 file changed, 7 insertions(+), 6 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index ce69723d318..ceb0f5a8e03 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -203,12 +203,6 @@ matrix:
             - CC=clang-3.8 make tsan-test-zstream
             - CC=clang-3.8 make tsan-fuzztest
     
    -    - name: Qemu PPC64 + Fuzz test  # ~13mn
    -      if: branch = master
    -      script:
    -        - make ppcinstall
    -        - make ppc64fuzz
    -
         - name: PPC64LE + Fuzz test  # ~13mn
           if: branch = master
           arch: ppc64le
    @@ -216,6 +210,13 @@ matrix:
             - cat /proc/cpuinfo
             - make test
     
    +    - name: Qemu PPC64 + Fuzz test  # ~13mn, presumed Big-Endian (?)
    +      dist: trusty  # note : PPC64 cross-compilation for Qemu tests seems broken on Xenial
    +      if: branch = master
    +      script:
    +        - make ppcinstall
    +        - make ppc64fuzz
    +
         # note : we already have aarch64 tests on hardware
         - name: Qemu aarch64 + Fuzz Test (on Xenial)    # ~14mn
           if: branch = master
    
    From 26b21e481f0f5bab1c29a5742580da15e995e33b Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 21 May 2020 14:19:28 -0700
    Subject: [PATCH 401/402] fix meson playTests.sh
    
    ---
     .travis.yml                   | 2 +-
     build/meson/tests/meson.build | 2 +-
     tests/playTests.sh            | 6 +++---
     3 files changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index ceb0f5a8e03..a4046287fea 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -243,7 +243,7 @@ matrix:
             - bash tests/libzstd_partial_builds.sh
     
         # meson dedicated test
    -    - name: Xenial (Meson + clang)    # ~8mn
    +    - name: Xenial (Meson + clang)    # ~15mn
           if: branch = master
           dist: xenial
           language: cpp
    diff --git a/build/meson/tests/meson.build b/build/meson/tests/meson.build
    index 728dba02d5a..0587f9a70d5 100644
    --- a/build/meson/tests/meson.build
    +++ b/build/meson/tests/meson.build
    @@ -158,7 +158,7 @@ if host_machine_os != os_windows
       test('test-zstd',
         playTests_sh,
         args: ZSTDRTTEST,
    -    env: ['ZSTD=' + zstd.full_path()],
    +    env: ['ZSTD_BIN=' + zstd.full_path(), 'DATAGEN_BIN=./datagen'],
         depends: [datagen],
         workdir: meson.current_build_dir(),
         timeout: 2800) # Timeout should work on HDD drive
    diff --git a/tests/playTests.sh b/tests/playTests.sh
    index 4ccf4bd24d9..f353229be7e 100755
    --- a/tests/playTests.sh
    +++ b/tests/playTests.sh
    @@ -123,10 +123,10 @@ case "$UNAME" in
       SunOS) DIFF="gdiff" ;;
     esac
     
    -println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN'"
    +println "\nStarting playTests.sh isWindows=$isWindows EXE_PREFIX='$EXE_PREFIX' ZSTD_BIN='$ZSTD_BIN' DATAGEN_BIN='$DATAGEN_BIN'"
     
    -[ -n "$ZSTD_BIN" ] || die "$ZSTD_BIN variable must be defined!"
    -[ -n "$DATAGEN_BIN" ] || die "$DATAGEN_BIN variable must be defined!"
    +[ -n "$ZSTD_BIN" ] || die "\$ZSTD_BIN variable must be defined!"
    +[ -n "$DATAGEN_BIN" ] || die "\$DATAGEN_BIN variable must be defined!"
     
     if echo hello | zstd -v -T2 2>&1 > $INTOVOID | grep -q 'multi-threading is disabled'
     then
    
    From 306e922f60158b9f8dcb9d4e2b3c641ebf0b8915 Mon Sep 17 00:00:00 2001
    From: Yann Collet 
    Date: Thu, 21 May 2020 18:06:43 -0700
    Subject: [PATCH 402/402] fixed environment variables
    
    ---
     appveyor.yml | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/appveyor.yml b/appveyor.yml
    index d09a136aeb0..5d77b310348 100644
    --- a/appveyor.yml
    +++ b/appveyor.yml
    @@ -169,8 +169,8 @@
       - SET "FUZZERTEST=-T30s"
       - if [%HOST%]==[visual] if [%CONFIGURATION%]==[Release] (
           CD tests &&
    -      SET ZSTD_BIN=zstd.exe &&
    -      SET DATAGEN_BIN=datagen.exe &&
    +      SET ZSTD_BIN=./zstd.exe&&
    +      SET DATAGEN_BIN=./datagen.exe&&
           sh -e playTests.sh --test-large-data &&
           fullbench.exe -i1 &&
           fullbench.exe -i1 -P0 &&