#define FNSPACE 30
+#define PATCHFROM_WINDOWSIZE_EXTRA_BYTES 1 KB
/*-*************************************
* Macros
int nbWorkers;
int excludeCompressedFiles;
+ int patchFromMode;
};
prefs->ldmHashRateLog = ldmHashRateLog;
}
+void FIO_setPatchFromMode(FIO_prefs_t* const prefs, int value)
+{
+ prefs->patchFromMode = value != 0;
+}
/*-*************************************
* Functions
* @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;
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));
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
/* **********************************************************************
} 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));
/* 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;
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) );
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);
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
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);
/* 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);
}
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
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;
/* 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);
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;
/* destination file name */
case 'o': nextArgumentIsOutFileName=1; lastCommand=1; argument++; break;
- /* limit decompression memory */
+ /* limit memory */
case 'M':
argument++;
memLimit = readU32FromChar(&argument);
} }
#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);
#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 {