diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | programs/Makefile | 8 | ||||
-rw-r--r-- | programs/bench.c | 8 | ||||
-rw-r--r-- | programs/bench.h | 4 | ||||
-rw-r--r-- | programs/lz4cli.c | 167 | ||||
-rw-r--r-- | programs/lz4io.c | 33 | ||||
-rw-r--r-- | programs/lz4io.h | 8 |
7 files changed, 132 insertions, 101 deletions
@@ -1,3 +1,8 @@ +r128: +New : command -m, to compress multiple files in a single command +Fixed : Restored lz4hc compression ratio (slightly lower since r124) +Added : Visual project directory + r126: New : lz4frame API is now integrated into liblz4 Fixed : GCC 4.9 bug on highest performance settings, reported by Greg Slazinski diff --git a/programs/Makefile b/programs/Makefile index 076d3bf..1070f40 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -31,7 +31,7 @@ # fullbench32: Same as fullbench, but forced to compile in 32-bits mode # ########################################################################## -RELEASE?= r126 +RELEASE?= r128 DESTDIR?= PREFIX ?= /usr @@ -158,6 +158,12 @@ test-lz4: lz4 datagen @rm *.test @echo frame concatenation test completed # test frame concatenation with null-length frame + @echo test multiple input files + @./datagen -s1 > file1 + @./datagen -s2 > file2 + @./datagen -s3 > file3 + ./lz4 -f -m file1 file2 file3 + @rm file1 file2 file3 file1.lz4 file2.lz4 file3.lz4 test-lz4c: lz4c datagen diff --git a/programs/bench.c b/programs/bench.c index 02e56c9..77120f2 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -1,6 +1,6 @@ /* bench.c - Demo program to benchmark open-source compression algorithm - Copyright (C) Yann Collet 2012-2014 + Copyright (C) Yann Collet 2012-2015 GPL v2 License This program is free software; you can redistribute it and/or modify @@ -215,7 +215,7 @@ static size_t BMK_findMaxMem(U64 requiredMem) } -static U64 BMK_GetFileSize(char* infilename) +static U64 BMK_GetFileSize(const char* infilename) { int r; #if defined(_MSC_VER) @@ -234,7 +234,7 @@ static U64 BMK_GetFileSize(char* infilename) * Public function **********************************************************/ -int BMK_benchFile(char** fileNamesTable, int nbFiles, int cLevel) +int BMK_benchFile(const char** fileNamesTable, int nbFiles, int cLevel) { int fileIdx=0; char* orig_buff; @@ -265,7 +265,7 @@ int BMK_benchFile(char** fileNamesTable, int nbFiles, int cLevel) while (fileIdx<nbFiles) { FILE* inFile; - char* inFileName; + const char* inFileName; U64 inFileSize; size_t benchedSize; int nbChunks; diff --git a/programs/bench.h b/programs/bench.h index d42df68..2a20cdb 100644 --- a/programs/bench.h +++ b/programs/bench.h @@ -1,6 +1,6 @@ /* bench.h - Demo program to benchmark open-source compression algorithm - Copyright (C) Yann Collet 2012-2014 + Copyright (C) Yann Collet 2012-2015 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ extern "C" { /* Main function */ -int BMK_benchFile(char** fileNamesTable, int nbFiles, int cLevel); +int BMK_benchFile(const char** fileNamesTable, int nbFiles, int cLevel); /* Set Parameters */ void BMK_SetBlocksize(int bsize); diff --git a/programs/lz4cli.c b/programs/lz4cli.c index 7524947..ef3ef65 100644 --- a/programs/lz4cli.c +++ b/programs/lz4cli.c @@ -1,6 +1,6 @@ /* LZ4cli - LZ4 Command Line Interface - Copyright (C) Yann Collet 2011-2014 + Copyright (C) Yann Collet 2011-2015 GPL v2 License @@ -85,7 +85,7 @@ ******************************/ #define COMPRESSOR_NAME "LZ4 command line interface" #ifndef LZ4_VERSION -# define LZ4_VERSION "r126" +# define LZ4_VERSION "r128" #endif #define AUTHOR "Yann Collet" #define WELCOME_MESSAGE "*** %s %i-bits %s, by %s (%s) ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), LZ4_VERSION, AUTHOR, __DATE__ @@ -136,7 +136,7 @@ static char* programName; #define EXTENDED_FORMAT #define DEFAULT_COMPRESSOR LZ4IO_compressFilename #define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename -int LZ4IO_compressFilename_Legacy(char* input_filename, char* output_filename, int compressionlevel); /* hidden function */ +int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel); /* hidden function */ /**************************** @@ -156,7 +156,7 @@ static int usage(void) DISPLAY( " -z : force compression\n"); DISPLAY( " -f : overwrite output without prompting \n"); DISPLAY( " -h/-H : display help/long help and exit\n"); - DISPLAY( " -m : allow mulitple input files (implies automatic output filenames)"); + DISPLAY( " -m : multiple input files (implies automatic output filenames)\n"); return 0; } @@ -262,32 +262,31 @@ int main(int argc, char** argv) cLevel=0, decode=0, bench=0, - filenamesStart=2, legacy_format=0, forceStdout=0, forceCompress=0, main_pause=0, multiple_inputs=0; - char* input_filename=0; + const char* input_filename=0; char* output_filename=0; char* dynNameSpace=0; - char *input_filenames[argc]; + const char** inFileNames = NULL; + unsigned ifnIdx=0; char nullOutput[] = NULL_OUTPUT; char extension[] = LZ4_EXTENSION; - int blockSize; + int blockSize; /* Init */ programName = argv[0]; LZ4IO_setOverwrite(0); blockSize = LZ4IO_setBlockSizeID(LZ4_BLOCKSIZEID_DEFAULT); - /* lz4cat behavior */ + /* lz4cat predefined behavior */ if (!strcmp(programName, LZ4_CAT)) { decode=1; forceStdout=1; output_filename=stdoutmark; displayLevel=1; } /* command switches */ for(i=1; i<argc; i++) { - input_filenames[i]=0; char* argument = argv[i]; if(!argument) continue; /* Protection if argument empty */ @@ -381,7 +380,7 @@ int main(int argc, char** argv) break; } case 'D': LZ4IO_setBlockMode(LZ4IO_blockLinked); argument++; break; - case 'X': LZ4IO_setBlockChecksumMode(1); argument ++; break; /* currently disables */ + case 'X': LZ4IO_setBlockChecksumMode(1); argument ++; break; /* currently disabled */ default : exitBlockProperties=1; } if (exitBlockProperties) break; @@ -392,10 +391,16 @@ int main(int argc, char** argv) case 'S': if (argument[1]=='x') { LZ4IO_setStreamChecksumMode(0); argument++; break; } else { badusage(); } /* Benchmark */ - case 'b': bench=1; break; + case 'b': bench=1; multiple_inputs=1; + if (inFileNames == NULL) + inFileNames = malloc(argc * sizeof(char*)); + break; - /* Treat non-option args as input files. See Issue 151 in Google Code */ - case 'm': multiple_inputs=1; break; + /* Treat non-option args as input files. See https://code.google.com/p/lz4/issues/detail?id=151 */ + case 'm': multiple_inputs=1; + if (inFileNames == NULL) + inFileNames = malloc(argc * sizeof(char*)); + break; /* Modify Nb Iterations (benchmark only) */ case 'i': @@ -420,11 +425,11 @@ int main(int argc, char** argv) continue; } - /* Input files are a wonderful thing. Store in *input_filenames[] if -m is used. */ - if (multiple_inputs) { input_filenames[i]=argument; continue; } + /* Store in *inFileNames[] if -m is used. */ + if (multiple_inputs) { inFileNames[ifnIdx++]=argument; continue; } /* Store first non-option arg in input_filename to preserve original cli logic. */ - if (!input_filename) { input_filename=argument; filenamesStart=i; continue; } + if (!input_filename) { input_filename=argument; continue; } /* Second non-option arg in output_filename to preserve original cli logic. */ if (!output_filename) @@ -433,95 +438,87 @@ int main(int argc, char** argv) if (!strcmp (output_filename, nullOutput)) output_filename = nulmark; continue; } - } - /* If we are not using multiple_inputs, clear *input_filesnames[] (just in case) and set element 0 to input_filename. */ - if (!multiple_inputs) - { - for (i=0; i<argc; i++) input_filenames[i]=0; + /* 3rd non-option arg should not exist */ + DISPLAYLEVEL(1, "Warning : %s won't be used ! Do you want multiple input files (-m) ? \n", argument); } - input_filenames[0]=input_filename; - /* Loop through all the input_filenames[], which should only be 1 if we're using the old (original, non -m) cli method. - This is a shamelessly-stolen loop over the original logic. */ - for (i=0; i<argc; i++) - { - if (!input_filenames[i]) continue; - input_filename=input_filenames[i]; - DISPLAYLEVEL(3, WELCOME_MESSAGE); - if (!decode) DISPLAYLEVEL(4, "Blocks size : %i KB\n", blockSize>>10); + DISPLAYLEVEL(3, WELCOME_MESSAGE); + if (!decode) DISPLAYLEVEL(4, "Blocks size : %i KB\n", blockSize>>10); - /* No input filename ==> use stdin */ - if(!input_filename) { input_filename=stdinmark; } + /* No input filename ==> use stdin */ + if (multiple_inputs) input_filename = inFileNames[0], output_filename = (char*)(inFileNames[0]); + if(!input_filename) { input_filename=stdinmark; } - /* Check if input or output are defined as console; trigger an error in this case */ - if (!strcmp(input_filename, stdinmark) && IS_CONSOLE(stdin) ) badusage(); + /* Check if input or output are defined as console; trigger an error in this case */ + if (!strcmp(input_filename, stdinmark) && IS_CONSOLE(stdin) ) badusage(); - /* Check if benchmark is selected */ - if (bench) return BMK_benchFile(argv+filenamesStart, argc-filenamesStart, cLevel); + /* Check if benchmark is selected */ + if (bench) return BMK_benchFile(inFileNames, ifnIdx, cLevel); - /* No output filename ==> try to select one automatically (when possible) */ - while (!output_filename) + /* No output filename ==> try to select one automatically (when possible) */ + while (!output_filename) + { + if (!IS_CONSOLE(stdout)) { output_filename=stdoutmark; break; } /* Default to stdout whenever possible (i.e. not a console) */ + if ((!decode) && !(forceCompress)) /* auto-determine compression or decompression, based on file extension */ { - if (!IS_CONSOLE(stdout)) { output_filename=stdoutmark; break; } /* Default to stdout whenever possible (i.e. not a console) */ - if ((!decode) && !(forceCompress)) /* auto-determine compression or decompression, based on file extension */ - { - size_t l = strlen(input_filename); - if (!strcmp(input_filename+(l-4), LZ4_EXTENSION)) decode=1; - } - if (!decode) /* compression to file */ - { - size_t l = strlen(input_filename); - dynNameSpace = (char*)calloc(1,l+5); - output_filename = dynNameSpace; - strcpy(output_filename, input_filename); - strcpy(output_filename+l, LZ4_EXTENSION); - DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename); - break; - } - /* decompression to file (automatic name will work only if input filename has correct format extension) */ - { - size_t outl; - size_t inl = strlen(input_filename); - dynNameSpace = (char*)calloc(1,inl+1); - output_filename = dynNameSpace; - strcpy(output_filename, input_filename); - outl = inl; - if (inl>4) - while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) output_filename[outl--]=0; - if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); badusage(); } - DISPLAYLEVEL(2, "Decoding file %s \n", output_filename); - } + size_t l = strlen(input_filename); + if (!strcmp(input_filename+(l-4), LZ4_EXTENSION)) decode=1; } + if (!decode) /* compression to file */ + { + size_t l = strlen(input_filename); + dynNameSpace = (char*)calloc(1,l+5); + output_filename = dynNameSpace; + strcpy(output_filename, input_filename); + strcat(output_filename, LZ4_EXTENSION); + DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename); + break; + } + /* decompression to file (automatic name will work only if input filename has correct format extension) */ + { + size_t outl; + size_t inl = strlen(input_filename); + dynNameSpace = (char*)calloc(1,inl+1); + output_filename = dynNameSpace; + strcpy(output_filename, input_filename); + outl = inl; + if (inl>4) + while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) output_filename[outl--]=0; + if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); badusage(); } + DISPLAYLEVEL(2, "Decoding file %s \n", output_filename); + } + } - /* Check if output is defined as console; trigger an error in this case */ - if (!strcmp(output_filename,stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) badusage(); + /* Check if output is defined as console; trigger an error in this case */ + if (!strcmp(output_filename,stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) badusage(); - /* No warning message in pure pipe mode (stdin + stdout) */ - if (!strcmp(input_filename, stdinmark) && !strcmp(output_filename,stdoutmark) && (displayLevel==2)) displayLevel=1; + /* No warning message in pure pipe mode (stdin + stdout) */ + if (!strcmp(input_filename, stdinmark) && !strcmp(output_filename,stdoutmark) && (displayLevel==2)) displayLevel=1; - /* IO Stream/File */ - LZ4IO_setNotificationLevel(displayLevel); - if (decode) DEFAULT_DECOMPRESSOR(input_filename, output_filename); + /* IO Stream/File */ + LZ4IO_setNotificationLevel(displayLevel); + if (decode) DEFAULT_DECOMPRESSOR(input_filename, output_filename); + else + { + /* compression is default action */ + if (legacy_format) + { + DISPLAYLEVEL(3, "! Generating compressed LZ4 using Legacy format (deprecated) ! \n"); + LZ4IO_compressFilename_Legacy(input_filename, output_filename, cLevel); + } else { - /* compression is default action */ - if (legacy_format) - { - DISPLAYLEVEL(3, "! Generating compressed LZ4 using Legacy format (deprecated) ! \n"); - LZ4IO_compressFilename_Legacy(input_filename, output_filename, cLevel); - } + if (multiple_inputs) + LZ4IO_compressMultipleFilenames(inFileNames, ifnIdx, LZ4_EXTENSION, cLevel); else - { DEFAULT_COMPRESSOR(input_filename, output_filename, cLevel); - } } - /* Clear the output_filename here in case there are other files to process. */ - output_filename=0; } if (main_pause) waitEnter(); free(dynNameSpace); + free((void*)inFileNames); return 0; } diff --git a/programs/lz4io.c b/programs/lz4io.c index 023824e..bc8f3ff 100644 --- a/programs/lz4io.c +++ b/programs/lz4io.c @@ -1,6 +1,6 @@ /* LZ4io.c - LZ4 File/Stream Interface - Copyright (C) Yann Collet 2011-2014 + Copyright (C) Yann Collet 2011-2015 GPL v2 License This program is free software; you can redistribute it and/or modify @@ -226,7 +226,7 @@ static int LZ4S_GetBlockSize_FromBlockId (int id) { return (1 << (8 + ( static int LZ4S_isSkippableMagicNumber(unsigned int magic) { return (magic & LZ4S_SKIPPABLEMASK) == LZ4S_SKIPPABLE0; } -static int get_fileHandle(char* input_filename, char* output_filename, FILE** pfinput, FILE** pfoutput) +static int get_fileHandle(const char* input_filename, const char* output_filename, FILE** pfinput, FILE** pfoutput) { if (!strcmp (input_filename, stdinmark)) @@ -293,7 +293,7 @@ static void LZ4IO_writeLE32 (void* p, unsigned value32) /* LZ4IO_compressFilename_Legacy : * This function is intentionally "hidden" (not published in .h) * It generates compressed streams using the old 'legacy' format */ -int LZ4IO_compressFilename_Legacy(char* input_filename, char* output_filename, int compressionlevel) +int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel) { int (*compressionFunction)(const char*, char*, int); unsigned long long filesize = 0; @@ -367,7 +367,7 @@ int LZ4IO_compressFilename_Legacy(char* input_filename, char* output_filename, i * Compression using Frame format * ********************************************/ -int LZ4IO_compressFilename(char* input_filename, char* output_filename, int compressionLevel) +int LZ4IO_compressFilename(const char* input_filename, const char* output_filename, int compressionLevel) { unsigned long long filesize = 0; unsigned long long compressedfilesize = 0; @@ -465,8 +465,29 @@ int LZ4IO_compressFilename(char* input_filename, char* output_filename, int comp } +int LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionlevel) +{ + int i; + char* outFileName = NULL; + size_t ofnSize = 0; + const size_t suffixSize = strlen(suffix); + + for (i=0; i<ifntSize; i++) + { + size_t ifnSize = strlen(inFileNamesTable[i]); + if (ofnSize <= ifnSize+suffixSize+1) { free(outFileName); ofnSize = ifnSize + 20; outFileName = malloc(ofnSize); } + strcpy(outFileName, inFileNamesTable[i]); + strcat(outFileName, suffix); + LZ4IO_compressFilename(inFileNamesTable[i], outFileName, compressionlevel); + } + free(outFileName); + return 0; +} + + + /* ********************************************************************* */ -/* ********************** LZ4 File / Stream decoding ******************* */ +/* ********************** LZ4 file-stream Decompression **************** */ /* ********************************************************************* */ static unsigned LZ4IO_readLE32 (const void* s) @@ -633,7 +654,7 @@ static unsigned long long selectDecoder( FILE* finput, FILE* foutput) } -int LZ4IO_decompressFilename(char* input_filename, char* output_filename) +int LZ4IO_decompressFilename(const char* input_filename, const char* output_filename) { unsigned long long filesize = 0, decodedSize=0; FILE* finput; diff --git a/programs/lz4io.h b/programs/lz4io.h index 7869a43..2270c65 100644 --- a/programs/lz4io.h +++ b/programs/lz4io.h @@ -1,6 +1,6 @@ /* LZ4io.h - LZ4 File/Stream Interface - Copyright (C) Yann Collet 2011-2014 + Copyright (C) Yann Collet 2011-2015 GPL v2 License This program is free software; you can redistribute it and/or modify @@ -47,8 +47,10 @@ static char nulmark[] = "/dev/null"; /* ****************** Functions ********************* */ /* ************************************************** */ -int LZ4IO_compressFilename (char* input_filename, char* output_filename, int compressionlevel); -int LZ4IO_decompressFilename(char* input_filename, char* output_filename); +int LZ4IO_compressFilename (const char* input_filename, const char* output_filename, int compressionlevel); +int LZ4IO_decompressFilename(const char* input_filename, const char* output_filename); + +int LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionlevel); /* ************************************************** */ |