Updated : cmake/CMakeLists.txt, by Nobuhiro Iwamatsu
Updated : cmake/pack/CMakeLists.txt, by Dmitry Cherepanov
lz4demo : CLI accept aggregated commands
lz4demo : detect overwrite output
lz4demo : new commands options (-hc, -y)

git-svn-id: https://lz4.googlecode.com/svn/trunk@91 650e7d94-2a16-8b24-b05c-7c0b3f6821cd
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 62bc347..3d3e558 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -83,6 +83,12 @@
         LIBRARY DESTINATION lib

         ARCHIVE DESTINATION lib

     )

+    

+    install(FILES

+        ${SRC_DIR}/lz4.h

+        ${SRC_DIR}/lz4hc.h

+        DESTINATION include)

+            

 endif(BUILD_SHARED_LIBS)

 

 

diff --git a/cmake/pack/CMakeLists.txt b/cmake/pack/CMakeLists.txt
index 80adbb3..6d23235 100644
--- a/cmake/pack/CMakeLists.txt
+++ b/cmake/pack/CMakeLists.txt
@@ -2,7 +2,7 @@
 PROJECT(LZ4)

 

 ############################## CPACK

-set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../)

+set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../)

 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LZ4 Packer")

 set(CPACK_PACKAGE_VERSION_MAJOR 0)

 set(CPACK_PACKAGE_VERSION_MINOR 0)

diff --git a/cmake/release_COPYING.txt b/cmake/release_COPYING.txt
deleted file mode 100644
index 32cec0d..0000000
--- a/cmake/release_COPYING.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-

-    lz4demo and fuzzer is an open-source demo compression algorithm LZ4 programs

-    Copyright (C) Yann Collet 2012

-

-    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

-    the Free Software Foundation; either version 2 of the License, or

-    (at your option) any later version.

-

-    This program is distributed in the hope that it will be useful,

-    but WITHOUT ANY WARRANTY; without even the implied warranty of

-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

-    GNU General Public License for more details.

-

-    You should have received a copy of the GNU General Public License along

-    with this program; if not, write to the Free Software Foundation, Inc.,

-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-

-	You can contact the author at :

-	- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html

-	- LZ4 source repository : http://code.google.com/p/lz4/

diff --git a/fuzzer.c b/fuzzer.c
index 11697fd..0a57f77 100644
--- a/fuzzer.c
+++ b/fuzzer.c
@@ -1,8 +1,8 @@
 /*

     fuzzer.c - Fuzzer test tool for LZ4

     Copyright (C) Andrew Mahone - Yann Collet 2012

-	Original code by Andrew Mahone / Modified by Yann Collet

-	GPL v2 License

+    Original code by Andrew Mahone / Modified by Yann Collet

+    GPL v2 License

 

     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

@@ -18,9 +18,9 @@
     with this program; if not, write to the Free Software Foundation, Inc.,

     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 

-	You can contact the author at :

-	- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html

-	- LZ4 source repository : http://code.google.com/p/lz4/

+    You can contact the author at :

+    - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html

+    - LZ4 source repository : http://code.google.com/p/lz4/

 */

 

 //**************************************

@@ -36,6 +36,7 @@
 #include <stdio.h>      // fgets, sscanf

 #include <sys/timeb.h>  // timeb

 #include "lz4.h"

+#include "lz4hc.h"

 

 

 //**************************************

@@ -79,8 +80,8 @@
 

 unsigned int FUZ_rand(unsigned int* src)

 {

-	*src =  ((*src) * PRIME1) + PRIME2;

-	return *src;

+    *src =  ((*src) * PRIME1) + PRIME2;

+    return *src;

 }

 

 

@@ -110,7 +111,7 @@
 

   free(input);

   free(output);

-  printf(" Completed (r=%i)\n",r);

+  printf(" Completed (return = %i < 0)\n",r);

   return 0;

 }

 

@@ -125,30 +126,30 @@
 #       define FUZ_avail ROUND_PAGE(FUZ_max)

         const int off_full = FUZ_avail - FUZ_max;

         unsigned char cbuf[FUZ_avail + PAGE_SIZE];

-		unsigned int seed, cur_seq=PRIME3, seeds[NUM_SEQ], timestamp=FUZ_GetMilliStart();

+        unsigned int seed, cur_seq=PRIME3, seeds[NUM_SEQ], timestamp=FUZ_GetMilliStart();

         int i, j, k, ret, len;

-		char userInput[30] = {0};

+        char userInput[30] = {0};

 

-		printf("starting LZ4 fuzzer\n");

-		printf("Select an Initialisation number (default : random) : ");

-		fflush(stdout);

-		if ( fgets(userInput, sizeof userInput, stdin) )

-		{

-			if ( sscanf(userInput, "%d", &seed) == 1 ) {}

-			else seed = FUZ_GetMilliSpan(timestamp);

-		}

-		printf("Seed = %u\n", seed);

+        printf("starting LZ4 fuzzer\n");

+        printf("Select an Initialisation number (default : random) : ");

+        fflush(stdout);

+        if ( fgets(userInput, sizeof userInput, stdin) )

+        {

+            if ( sscanf(userInput, "%d", &seed) == 1 ) {}

+            else seed = FUZ_GetMilliSpan(timestamp);

+        }

+        printf("Seed = %u\n", seed);

 

-		FUZ_SecurityTest();

+        FUZ_SecurityTest();

 

-		for (i = 0; i < 2048; i++)

+        for (i = 0; i < 2048; i++)

                 cbuf[FUZ_avail + i] = cbuf[FUZ_avail + 2048 + i] = FUZ_rand(&seed) >> 16;

 

         for (i = 0; i < NB_ATTEMPTS; i++) 

         {

-			printf("\r%7i /%7i\r", i, NB_ATTEMPTS);

-			

-			FUZ_rand(&seed);

+            printf("\r%7i /%7i\r", i, NB_ATTEMPTS);

+            

+            FUZ_rand(&seed);

             for (j = 0; j < NUM_SEQ; j++) {

                     seeds[j] = FUZ_rand(&seed) << 8;

                     seeds[j] ^= (FUZ_rand(&seed) >> 8) & 65535;

@@ -165,63 +166,63 @@
                     buf[j] = FUZ_rand(&cur_seq) >> 16;

             }

 

-			// Test compression

+            // Test compression

             ret = LZ4_compress_limitedOutput((const char*)buf, (char*)&cbuf[off_full], LEN, FUZ_max);

-			if (ret == 0) { printf("compression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

+            if (ret == 0) { printf("compression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

             len = ret;

 

-			// Test decoding with output size being exactly what's necessary => must work

-			ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN);

-			if (ret<0) { printf("decompression failed despite correct space: seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with output size being exactly what's necessary => must work

+            ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN);

+            if (ret<0) { printf("decompression failed despite correct space: seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with one byte missing => must fail

-			ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN-1);

-			if (ret>=0) { printf("decompression should have failed, due to Output Size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with one byte missing => must fail

+            ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN-1);

+            if (ret>=0) { printf("decompression should have failed, due to Output Size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with one byte too much => must fail

-			ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN+1);

-			if (ret>=0) { printf("decompression should have failed, due to Output Size being too large : seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with one byte too much => must fail

+            ret = LZ4_uncompress((char*)&cbuf[off_full], (char*)testOut, LEN+1);

+            if (ret>=0) { printf("decompression should have failed, due to Output Size being too large : seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with enough output size => must work

-			ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN+1);

-			if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with enough output size => must work

+            ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN+1);

+            if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with output size being exactly what's necessary => must work

-			ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN);

-			if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with output size being exactly what's necessary => must work

+            ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN);

+            if (ret<0) { printf("decompression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with output size being one byte too short => must fail

-			ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN-1);

-			if (ret>=0) { printf("decompression should have failed, due to Output Size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with output size being one byte too short => must fail

+            ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len, LEN-1);

+            if (ret>=0) { printf("decompression should have failed, due to Output Size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with input size being one byte too short => must fail

-			ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len-1, LEN);

-			if (ret>=0) { printf("decompression should have failed, due to input size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with input size being one byte too short => must fail

+            ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len-1, LEN);

+            if (ret>=0) { printf("decompression should have failed, due to input size being too small : seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test decoding with input size being one byte too large => must fail

-			ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len+1, LEN);

-			if (ret>=0) { printf("decompression should have failed, due to input size being too large : seed %u, len %d\n", seed, LEN); goto _output_error; }

+            // Test decoding with input size being one byte too large => must fail

+            ret = LZ4_uncompress_unknownOutputSize((char*)&cbuf[off_full], (char*)testOut, len+1, LEN);

+            if (ret>=0) { printf("decompression should have failed, due to input size being too large : seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test compression with output size being exactly what's necessary (should work)

+            // Test compression with output size being exactly what's necessary (should work)

             ret = LZ4_compress_limitedOutput((const char*)buf, (char*)&cbuf[FUZ_avail-len], LEN, len);

             if (!test_canary(&cbuf[FUZ_avail])) { printf("compression overran output buffer: seed %u, len %d, olen %d\n", seed, LEN, len); goto _output_error; }

             if (ret == 0) { printf("compression failed despite sufficient space: seed %u, len %d\n", seed, LEN); goto _output_error; }

 

-			// Test compression with just one missing byte into output buffer => must fail

+            // Test compression with just one missing byte into output buffer => must fail

             ret = LZ4_compress_limitedOutput((const char*)buf, (char*)&cbuf[FUZ_avail-(len-1)], LEN, len-1);

             if (ret) { printf("compression overran output buffer: seed %u, len %d, olen %d => ret %d", seed, LEN, len-1, ret); goto _output_error; }

             if (!test_canary(&cbuf[FUZ_avail])) { printf("compression overran output buffer: seed %u, len %d, olen %d", seed, LEN, len-1); goto _output_error; }

 

-			bytes += LEN;

+            bytes += LEN;

             cbytes += len;

         }

 

-		printf("all tests completed successfully \n");

+        printf("all tests completed successfully \n");

         printf("compression ratio: %0.3f%%\n", (double)cbytes/bytes*100);

-		getchar();

+        getchar();

         return 0;

 

 _output_error:

-		getchar();

-		return 1;

+        getchar();

+        return 1;

 }

diff --git a/lz4.c b/lz4.c
index 1f2eafd..f15dcfc 100644
--- a/lz4.c
+++ b/lz4.c
@@ -710,6 +710,7 @@
 //		are safe against "buffer overflow" attack type.

 //		They will never write nor read outside of the provided output buffers.

 //      LZ4_uncompress_unknownOutputSize() also insures that it will never read outside of the input buffer.

+//      LZ4_uncompress() guarantees that it will never read before source, nor beyond source + LZ4_compressBound(osize)

 //		A corrupted input will produce an error result, a negative int, indicating the position of the error within input stream.

 

 int LZ4_uncompress(const char* source,

diff --git a/lz4.h b/lz4.h
index 4897eb2..b50e98d 100644
--- a/lz4.h
+++ b/lz4.h
@@ -66,7 +66,7 @@
 

 LZ4_uncompress() :

     osize  : is the output size, therefore the original size

-    return : the number of bytes read in the source buffer

+    return : the number of bytes read in the source buffer (in other words, the compressed size)

              If the source stream is malformed, the function will stop decoding and return a negative result, indicating the byte position of the faulty instruction

              This function never writes outside of provided buffers, and never modifies input buffer.

     note : destination buffer must be already allocated.

diff --git a/lz4demo.c b/lz4demo.c
index 85edcf0..9103c8b 100644
--- a/lz4demo.c
+++ b/lz4demo.c
@@ -1,31 +1,31 @@
 /*

-    LZ4Demo - Demo CLI program using LZ4 compression

-    Copyright (C) Yann Collet 2011-2012

-	GPL v2 License

+  LZ4Demo - Demo CLI program using LZ4 compression

+  Copyright (C) Yann Collet 2011-2012

+  GPL v2 License

 

-    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

-    the Free Software Foundation; either version 2 of the License, or

-    (at your option) any later version.

+  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

+  the Free Software Foundation; either version 2 of the License, or

+  (at your option) any later version.

 

-    This program is distributed in the hope that it will be useful,

-    but WITHOUT ANY WARRANTY; without even the implied warranty of

-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

-    GNU General Public License for more details.

+  This program is distributed in the hope that it will be useful,

+  but WITHOUT ANY WARRANTY; without even the implied warranty of

+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+  GNU General Public License for more details.

 

-    You should have received a copy of the GNU General Public License along

-    with this program; if not, write to the Free Software Foundation, Inc.,

-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

+  You should have received a copy of the GNU General Public License along

+  with this program; if not, write to the Free Software Foundation, Inc.,

+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 

-	You can contact the author at :

-	- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html

-	- LZ4 source repository : http://code.google.com/p/lz4/

+  You can contact the author at :

+  - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html

+  - LZ4 source repository : http://code.google.com/p/lz4/

 */

 /*

-	Note : this is *only* a demo program, an example to show how LZ4 can be used.

-	It is not considered part of LZ4 compression library.

-	The license of LZ4 is BSD.

-	The license of the demo program is GPL.

+  Note : this is *only* a demo program, an example to show how LZ4 can be used.

+  It is not considered part of LZ4 compression library.

+  The license of LZ4 is BSD.

+  The license of the demo program is GPL.

 */

 

 //**************************************

@@ -63,11 +63,11 @@
 #define swap32 __builtin_bswap32

 #else

 static inline unsigned int swap32(unsigned int x) {

-			return	((x << 24) & 0xff000000 ) |

-				((x <<  8) & 0x00ff0000 ) |

-				((x >>  8) & 0x0000ff00 ) |

-				((x >> 24) & 0x000000ff );

-		 }

+    return	((x << 24) & 0xff000000 ) |

+        ((x <<  8) & 0x00ff0000 ) |

+        ((x >>  8) & 0x0000ff00 ) |

+        ((x >> 24) & 0x000000ff );

+}

 #endif

 

 

@@ -102,301 +102,381 @@
 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)

 

 

+//**************************************

+// Special input/output

+//**************************************

+#define NULL_INPUT "null"

+char stdinmark[] = "stdin";

+char stdoutmark[] = "stdout";

+#ifdef _WIN32

+char nulmark[] = "nul";

+#else

+char nulmark[] = "/dev/null";

+#endif

+

+

+//**************************************

+// I/O Parameters

+//**************************************

+static int overwrite = 0;

+

+

+

 //****************************

 // Functions

 //****************************

 int usage(char* exename)

 {

-	DISPLAY( "Usage :\n");

-	DISPLAY( "      %s [arg] input output\n", exename);

-	DISPLAY( "Arguments :\n");

-	DISPLAY( " -c0: Fast compression (default) \n");

-	DISPLAY( " -c1: High compression \n");

-	DISPLAY( " -d : decompression \n");

-	DISPLAY( " -b#: Benchmark files, using # compression level\n");

-	DISPLAY( " -t : check compressed file \n");

-	DISPLAY( " -h : help (this text)\n");

-	DISPLAY( "input  : can be 'stdin' (pipe) or a filename\n");

-	DISPLAY( "output : can be 'stdout'(pipe) or a filename or 'null'\n");

-	return 0;

+    DISPLAY( "Usage :\n");

+    DISPLAY( "      %s [arg] input output\n", exename);

+    DISPLAY( "Arguments :\n");

+    DISPLAY( " -c0/-c : Fast compression (default) \n");

+    DISPLAY( " -c1/-hc: High compression \n");

+    DISPLAY( " -d     : decompression \n");

+    DISPLAY( " -y     : overwrite output \n");

+    DISPLAY( " -t     : check compressed file \n");

+    DISPLAY( " -b#    : Benchmark files, using # compression level\n");

+    DISPLAY( " -H     : help (this text)\n");

+    DISPLAY( "input   : can be 'stdin' (pipe) or a filename\n");

+    DISPLAY( "output  : can be 'stdout'(pipe) or a filename or 'null'\n");

+    return 0;

 }

 

 

 int badusage(char* exename)

 {

-	DISPLAY("Wrong parameters\n");

-	usage(exename);

-	return 0;

+    DISPLAY("Wrong parameters\n");

+    usage(exename);

+    return 0;

 }

 

 

-

 int get_fileHandle(char* input_filename, char* output_filename, FILE** pfinput, FILE** pfoutput)

 {

-	char stdinmark[] = "stdin";

-	char stdoutmark[] = "stdout";

 

-	if (!strcmp (input_filename, stdinmark)) {

-		DISPLAY( "Using stdin for input\n");

-		*pfinput = stdin;

+    if (!strcmp (input_filename, stdinmark)) 

+    {

+        DISPLAY( "Using stdin for input\n");

+        *pfinput = stdin;

 #ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows

-		_setmode( _fileno( stdin ), _O_BINARY );

+        _setmode( _fileno( stdin ), _O_BINARY );

 #endif

-	} else {

-		*pfinput = fopen( input_filename, "rb" );

-	}

+    } 

+    else 

+    {

+        *pfinput = fopen(input_filename, "rb");

+    }

 

-	if (!strcmp (output_filename, stdoutmark)) {

-		DISPLAY( "Using stdout for output\n");

-		*pfoutput = stdout;

+    if (!strcmp (output_filename, stdoutmark)) 

+    {

+        DISPLAY( "Using stdout for output\n");

+        *pfoutput = stdout;

 #ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows

-		_setmode( _fileno( stdout ), _O_BINARY );

+        _setmode( _fileno( stdout ), _O_BINARY );

 #endif

-	} else {

-		*pfoutput = fopen( output_filename, "wb" );

-	}

+    } 

+    else 

+    {

+        // Check if destination file already exists

+        *pfoutput=0;

+        if (output_filename != nulmark) *pfoutput = fopen( output_filename, "rb" );

+        if (*pfoutput!=0) 

+        { 

+            char ch;

+            fclose(*pfoutput); 

+            DISPLAY( "Warning : %s already exists\n", output_filename); 

+            if (!overwrite)

+            {

+                DISPLAY( "Overwrite ? (Y/N) : ");

+                ch = getchar();

+                if (ch!='Y') { DISPLAY( "Operation aborted : %s already exists\n", output_filename);  return 12; }

+            }

+        }

+        *pfoutput = fopen( output_filename, "wb" );

+    }

 

-	if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename);  return 2; }

-	if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 3; }

+    if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename);  return 13; }

+    if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 14; }

 

-	return 0;

+    return 0;

 }

 

 

 

 int compress_file(char* input_filename, char* output_filename, int compressionlevel)

 {

-	int (*compressionFunction)(const char*, char*, int);

-	unsigned long long filesize = 0;

-	unsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;

-	unsigned int u32var;

-	char* in_buff;

-	char* out_buff;

-	FILE* finput;

-	FILE* foutput;

-	int r;

-	int displayLevel = (compressionlevel>0);

-	clock_t start, end;

-	size_t sizeCheck;

+    int (*compressionFunction)(const char*, char*, int);

+    unsigned long long filesize = 0;

+    unsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;

+    unsigned int u32var;

+    char* in_buff;

+    char* out_buff;

+    FILE* finput;

+    FILE* foutput;

+    int r;

+    int displayLevel = (compressionlevel>0);

+    clock_t start, end;

+    size_t sizeCheck;

 

 

-	// Init

-	switch (compressionlevel)

-	{

-	case 0 : compressionFunction = LZ4_compress; break;

-	case 1 : compressionFunction = LZ4_compressHC; break;

-	default : compressionFunction = LZ4_compress;

-	}

-	start = clock();

-	r = get_fileHandle(input_filename, output_filename, &finput, &foutput);

-	if (r) return r;

+    // Init

+    switch (compressionlevel)

+    {

+    case 0 : compressionFunction = LZ4_compress; break;

+    case 1 : compressionFunction = LZ4_compressHC; break;

+    default : compressionFunction = LZ4_compress;

+    }

+    start = clock();

+    r = get_fileHandle(input_filename, output_filename, &finput, &foutput);

+    if (r) return r;

 

-	// Allocate Memory

-	in_buff = (char*)malloc(CHUNKSIZE);

-	out_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));

-	if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 8; }

+    // Allocate Memory

+    in_buff = (char*)malloc(CHUNKSIZE);

+    out_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));

+    if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 21; }

 

-	// Write Archive Header

-	u32var = ARCHIVE_MAGICNUMBER;

-	LITTLE_ENDIAN32(u32var);

-	*(unsigned int*)out_buff = u32var;

-	sizeCheck = fwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);

-	if (sizeCheck!=ARCHIVE_MAGICNUMBER_SIZE) { DISPLAY("write error\n"); return 10; }

+    // Write Archive Header

+    u32var = ARCHIVE_MAGICNUMBER;

+    LITTLE_ENDIAN32(u32var);

+    *(unsigned int*)out_buff = u32var;

+    sizeCheck = fwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);

+    if (sizeCheck!=ARCHIVE_MAGICNUMBER_SIZE) { DISPLAY("write error\n"); return 22; }

 

-	// Main Loop

-	while (1)

-	{

-		int outSize;

-		// Read Block

-	    int inSize = (int) fread(in_buff, (size_t)1, (size_t)CHUNKSIZE, finput);

-		if( inSize<=0 ) break;

-		filesize += inSize;

-		if (displayLevel) DISPLAY("Read : %i MB  \r", (int)(filesize>>20));

+    // Main Loop

+    while (1)

+    {

+        int outSize;

+        // Read Block

+        int inSize = (int) fread(in_buff, (size_t)1, (size_t)CHUNKSIZE, finput);

+        if( inSize<=0 ) break;

+        filesize += inSize;

+        if (displayLevel) DISPLAY("Read : %i MB  \r", (int)(filesize>>20));

 

-		// Compress Block

-		outSize = compressionFunction(in_buff, out_buff+4, inSize);

-		compressedfilesize += outSize+4;

-		if (displayLevel) DISPLAY("Read : %i MB  ==> %.2f%%\r", (int)(filesize>>20), (double)compressedfilesize/filesize*100);

+        // Compress Block

+        outSize = compressionFunction(in_buff, out_buff+4, inSize);

+        compressedfilesize += outSize+4;

+        if (displayLevel) DISPLAY("Read : %i MB  ==> %.2f%%\r", (int)(filesize>>20), (double)compressedfilesize/filesize*100);

 

-		// Write Block

-		LITTLE_ENDIAN32(outSize);

-		* (unsigned int*) out_buff = outSize;

-		LITTLE_ENDIAN32(outSize);

-		sizeCheck = fwrite(out_buff, 1, outSize+4, foutput);

-		if (sizeCheck!=(size_t)(outSize+4)) { DISPLAY("write error\n"); return 11; }

-	}

+        // Write Block

+        LITTLE_ENDIAN32(outSize);

+        * (unsigned int*) out_buff = outSize;

+        LITTLE_ENDIAN32(outSize);

+        sizeCheck = fwrite(out_buff, 1, outSize+4, foutput);

+        if (sizeCheck!=(size_t)(outSize+4)) { DISPLAY("write error\n"); return 11; }

+    }

 

-	// Status

-	end = clock();

-	DISPLAY( "Compressed %llu bytes into %llu bytes ==> %.2f%%\n",

-		(unsigned long long) filesize, (unsigned long long) compressedfilesize, (double)compressedfilesize/filesize*100);

-	{

-		double seconds = (double)(end - start)/CLOCKS_PER_SEC;

-		DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);

-	}

+    // Status

+    end = clock();

+    DISPLAY( "Compressed %llu bytes into %llu bytes ==> %.2f%%\n",

+        (unsigned long long) filesize, (unsigned long long) compressedfilesize, (double)compressedfilesize/filesize*100);

+    {

+        double seconds = (double)(end - start)/CLOCKS_PER_SEC;

+        DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);

+    }

 

-	// Close & Free

-	free(in_buff);

-	free(out_buff);

-	fclose(finput);

-	fclose(foutput);

+    // Close & Free

+    free(in_buff);

+    free(out_buff);

+    fclose(finput);

+    fclose(foutput);

 

-	return 0;

+    return 0;

 }

 

 

 int decode_file(char* input_filename, char* output_filename)

 {

-	unsigned long long filesize = 0;

-	char* in_buff;

-	char* out_buff;

-	size_t uselessRet;

-	int sinkint;

-	unsigned int chunkSize;

-	FILE* finput;

-	FILE* foutput;

-	clock_t start, end;

-	int r;

-	size_t sizeCheck;

+    unsigned long long filesize = 0;

+    char* in_buff;

+    char* out_buff;

+    size_t uselessRet;

+    int sinkint;

+    unsigned int chunkSize;

+    FILE* finput;

+    FILE* foutput;

+    clock_t start, end;

+    int r;

+    size_t sizeCheck;

 

 

-	// Init

-	start = clock();

-	r = get_fileHandle(input_filename, output_filename, &finput, &foutput);

-	if (r) return r;

+    // Init

+    start = clock();

+    r = get_fileHandle(input_filename, output_filename, &finput, &foutput);

+    if (r) return r;

 

-	// Allocate Memory

-	in_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));

-	out_buff = (char*)malloc(CHUNKSIZE);

-	if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 7; }

+    // Allocate Memory

+    in_buff = (char*)malloc(LZ4_compressBound(CHUNKSIZE));

+    out_buff = (char*)malloc(CHUNKSIZE);

+    if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 31; }

 

-	// Check Archive Header

-	chunkSize = 0;

-	uselessRet = fread(&chunkSize, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);

-	LITTLE_ENDIAN32(chunkSize);

-	if (chunkSize != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 6; }

+    // Check Archive Header

+    chunkSize = 0;

+    uselessRet = fread(&chunkSize, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);

+    LITTLE_ENDIAN32(chunkSize);

+    if (chunkSize != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 32; }

 

-	// Main Loop

-	while (1)

-	{

-		// Block Size

-		uselessRet = fread(&chunkSize, 1, 4, finput);

-		if( uselessRet==0 ) break;   // Nothing to read : file read is completed

-		LITTLE_ENDIAN32(chunkSize);

-		if (chunkSize == ARCHIVE_MAGICNUMBER) 

-			continue;   // appended compressed stream

-		

-		// Read Block

-	    uselessRet = fread(in_buff, 1, chunkSize, finput);

+    // Main Loop

+    while (1)

+    {

+        // Block Size

+        uselessRet = fread(&chunkSize, 1, 4, finput);

+        if( uselessRet==0 ) break;   // Nothing to read : file read is completed

+        LITTLE_ENDIAN32(chunkSize);

+        if (chunkSize == ARCHIVE_MAGICNUMBER) 

+            continue;   // appended compressed stream

 

-		// Decode Block

-		sinkint = LZ4_uncompress_unknownOutputSize(in_buff, out_buff, chunkSize, CHUNKSIZE);

-		if (sinkint < 0) { DISPLAY("Decoding Failed ! Corrupted input !\n"); return 9; }

-		filesize += sinkint;

+        // Read Block

+        uselessRet = fread(in_buff, 1, chunkSize, finput);

 

-		// Write Block

-		sizeCheck = fwrite(out_buff, 1, sinkint, foutput);

-		if (sizeCheck != (size_t)sinkint) { DISPLAY("write error\n"); return 12; }

-	}

+        // Decode Block

+        sinkint = LZ4_uncompress_unknownOutputSize(in_buff, out_buff, chunkSize, CHUNKSIZE);

+        if (sinkint < 0) { DISPLAY("Decoding Failed ! Corrupted input !\n"); return 33; }

+        filesize += sinkint;

 

-	// Status

-	end = clock();

-	DISPLAY( "Successfully decoded %llu bytes \n", (unsigned long long)filesize);

-	{

-		double seconds = (double)(end - start)/CLOCKS_PER_SEC;

-		DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);

-	}

+        // Write Block

+        sizeCheck = fwrite(out_buff, 1, sinkint, foutput);

+        if (sizeCheck != (size_t)sinkint) { DISPLAY("write error\n"); return 34; }

+    }

 

-	// Close & Free

-	free(in_buff);

-	free(out_buff);

-	fclose(finput);

-	fclose(foutput);

+    // Status

+    end = clock();

+    DISPLAY( "Successfully decoded %llu bytes \n", (unsigned long long)filesize);

+    {

+        double seconds = (double)(end - start)/CLOCKS_PER_SEC;

+        DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);

+    }

 

-	return 0;

+    // Close & Free

+    free(in_buff);

+    free(out_buff);

+    fclose(finput);

+    fclose(foutput);

+

+    return 0;

 }

 

 

 int main(int argc, char** argv)

 {

-  int i,

-	  cLevel=0,

-	  decode=0,

-	  bench=0,

-	  filenamesStart=2;

-  char* exename=argv[0];

-  char* input_filename=0;

-  char* output_filename=0;

-#ifdef _WIN32

-  char nulmark[] = "nul";

-#else

-  char nulmark[] = "/dev/null";

-#endif

-  char nullinput[] = "null";

+    int i,

+        cLevel=0,

+        decode=0,

+        bench=0,

+        filenamesStart=2;

+    char* exename=argv[0];

+    char* input_filename=0;

+    char* output_filename=0;

+    char nullinput[] = NULL_INPUT;

+    char extension[] = EXTENSION;

 

-  // Welcome message

-  DISPLAY( WELCOME_MESSAGE);

+    // Welcome message

+    DISPLAY( WELCOME_MESSAGE);

 

-  if (argc<2) { badusage(exename); return 1; }

+    if (argc<2) { badusage(exename); return 1; }

 

-  for(i=1; i<argc; i++)

-  {

-    char* argument = argv[i];

+    for(i=1; i<argc; i++)

+    {

+        char* argument = argv[i];

 

-    if(!argument) continue;   // Protection if argument empty

+        if(!argument) continue;   // Protection if argument empty

 

-	// Select command

-	if (argument[0]=='-')

-	{

-		argument ++;

+        // Decode command (note : aggregated commands are allowed)

+        if (argument[0]=='-')

+        {

+            while (argument[1]!=0)

+            {

+                argument ++;

 

-		// Display help on usage

-		if ( argument[0] =='h' ) { usage(exename); return 0; }

+                switch(argument[0])

+                {

+                    // Display help on usage

+                case 'H': usage(exename); return 0;

 

-		// Compression (default)

-		if ( argument[0] =='c' ) { if (argument[1] >='0') cLevel=argument[1] - '0'; continue; }

+                    // Compression (default)

+                case 'c': if ((argument[1] >='0') && (argument[1] <='1')) { cLevel=argument[1] - '0'; argument++; } break;

+                case 'h': if (argument[1]=='c') { cLevel=1; argument++; } break;

 

-		// Decoding

-		if ( argument[0] =='d' ) { decode=1; continue; }

+                    // Decoding

+                case 'd': decode=1; break;

 

-		// Bench

-		if ( argument[0] =='b' ) { bench=1; if (argument[1] >= '0') cLevel=argument[1] - '0'; continue; } 

+                    // Bench

+                case 'b': bench=1; 

+                    if ((argument[1] >='0') && (argument[1] <='1')) { cLevel=argument[1] - '0'; argument++; } 

+                    break;

 

-		// Modify Block Size (benchmark only)

-		if ( argument[0] =='B' ) { int B = argument[1] - '0'; int S = 1 << (10 + 2*B); BMK_SetBlocksize(S); continue; }

+                    // Modify Block Size (benchmark only)

+                case 'B': 

+                    if ((argument[1] >='0') && (argument[1] <='9')) 

+                    { 

+                        int B = argument[1] - '0'; 

+                        int S = 1 << (10 + 2*B); BMK_SetBlocksize(S); 

+                        argument++;

+                    }  

+                    break;

 

-		// Modify Nb Iterations (benchmark only)

-		if ( argument[0] =='i' ) { int iters = argument[1] - '0'; BMK_SetNbIterations(iters); continue; }

+                    // Modify Nb Iterations (benchmark only)

+                case 'i': 

+                    if ((argument[1] >= '0') && (argument[1] <= '9'))

+                    {

+                        int iters = argument[1] - '0'; 

+                        BMK_SetNbIterations(iters); 

+                        argument++;

+                    }

+                    break;

 

-		// Pause at the end (benchmark only)

-		if ( argument[0] =='p' ) { BMK_SetPause(); continue; }

+                    // Pause at the end (benchmark only)

+                case 'p': BMK_SetPause(); break;

 

-        // Test

-		if ( argument[0] =='t' ) { decode=1; output_filename=nulmark; continue; }

-	}

+                    // Test

+                case 't': decode=1; output_filename=nulmark; break;

 

-	// first provided filename is input

-    if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }

+                    // Overwrite

+                case 'y': overwrite=1; break;

 

-	// second provided filename is output

-    if (!output_filename)

-	{

-		output_filename=argument;

-		if (!strcmp (output_filename, nullinput)) output_filename = nulmark;

-		continue;

-	}

-  }

+                    // Unrecognised command

+                default : badusage(exename); return 1;

+                }

+            }

+            continue;

+        }

 

-  // No input filename ==> Error

-  if(!input_filename) { badusage(exename); return 1; }

+        // first provided filename is input

+        if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }

 

-  if (bench) return BMK_benchFile(argv+filenamesStart, argc-filenamesStart, cLevel);

+        // second provided filename is output

+        if (!output_filename)

+        {

+            output_filename=argument;

+            if (!strcmp (output_filename, nullinput)) output_filename = nulmark;

+            continue;

+        }

+    }

 

-  // No output filename ==> Error

-  if (!output_filename) { badusage(exename); return 1; }

+    // No input filename ==> Error

+    if(!input_filename) { badusage(exename); return 1; }

 

-  if (decode) return decode_file(input_filename, output_filename);

+    if (bench) return BMK_benchFile(argv+filenamesStart, argc-filenamesStart, cLevel);

 

-  return compress_file(input_filename, output_filename, cLevel);   // Compression is 'default' action

+    // No output filename ==> build one automatically (for compression only)

+    if (!output_filename) 

+    { 

+        if (!decode)

+        {

+            int i=0, l=0;

+            while (input_filename[l]!=0) l++;

+            output_filename = (char*)calloc(1,l+5);

+            for (i=0;i<l;i++) output_filename[i] = input_filename[i];

+            for (i=l;i<l+4;i++) output_filename[i] = extension[i-l];

+        }

+        else

+        {

+            badusage(exename); 

+            return 1; 

+        }

+    }

+

+    if (decode) return decode_file(input_filename, output_filename);

+

+    return compress_file(input_filename, output_filename, cLevel);   // Compression is 'default' action

 

 }