/*\r
bench.c - Demo program to benchmark open-source compression algorithm\r
Copyright (C) Yann Collet 2012-2013\r
- GPL v2 License\r
+ GPL v2 License\r
\r
This program is free software; you can redistribute it and/or modify\r
it under the terms of the GNU General Public License as published by\r
with this program; if not, write to the Free Software Foundation, Inc.,\r
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
\r
- You can contact the author at :\r
- - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\r
- - LZ4 source repository : http://code.google.com/p/lz4/\r
+ You can contact the author at :\r
+ - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\r
+ - LZ4 source repository : http://code.google.com/p/lz4/\r
*/\r
\r
//**************************************\r
//**************************************\r
// Basic Types\r
//**************************************\r
-#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively\r
-#define BYTE unsigned __int8\r
-#define U16 unsigned __int16\r
-#define U32 unsigned __int32\r
-#define S32 __int32\r
-#define U64 unsigned __int64\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
+# include <stdint.h>\r
+ typedef uint8_t BYTE;\r
+ typedef uint16_t U16;\r
+ typedef uint32_t U32;\r
+ typedef int32_t S32;\r
+ typedef uint64_t U64;\r
#else\r
-#include <stdint.h>\r
-#define BYTE uint8_t\r
-#define U16 uint16_t\r
-#define U32 uint32_t\r
-#define S32 int32_t\r
-#define U64 uint64_t\r
+ typedef unsigned char BYTE;\r
+ typedef unsigned short U16;\r
+ typedef unsigned int U32;\r
+ typedef signed int S32;\r
+ typedef unsigned long long U64;\r
#endif\r
\r
\r
//**************************************\r
struct chunkParameters\r
{\r
- U32 id;\r
- char* origBuffer;\r
- char* compressedBuffer;\r
- int origSize;\r
- int compressedSize;\r
+ U32 id;\r
+ char* origBuffer;\r
+ char* compressedBuffer;\r
+ int origSize;\r
+ int compressedSize;\r
};\r
\r
struct compressionParameters\r
{\r
- int (*compressionFunction)(const char*, char*, int);\r
- int (*decompressionFunction)(const char*, char*, int);\r
+ int (*compressionFunction)(const char*, char*, int);\r
+ int (*decompressionFunction)(const char*, char*, int);\r
};\r
\r
\r
\r
void BMK_SetBlocksize(int bsize)\r
{\r
- chunkSize = bsize;\r
- DISPLAY("-Using Block Size of %i KB-\n", chunkSize>>10);\r
+ chunkSize = bsize;\r
+ DISPLAY("-Using Block Size of %i KB-\n", chunkSize>>10);\r
}\r
\r
void BMK_SetNbIterations(int nbLoops)\r
{\r
- nbIterations = nbLoops;\r
- DISPLAY("- %i iterations -\n", nbIterations);\r
+ nbIterations = nbLoops;\r
+ DISPLAY("- %i iterations -\n", nbIterations);\r
}\r
\r
void BMK_SetPause()\r
\r
static size_t BMK_findMaxMem(U64 requiredMem)\r
{\r
- size_t step = (64U<<20); // 64 MB\r
- BYTE* testmem=NULL;\r
+ size_t step = (64U<<20); // 64 MB\r
+ BYTE* testmem=NULL;\r
\r
- requiredMem = (((requiredMem >> 25) + 1) << 26);\r
- if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;\r
+ requiredMem = (((requiredMem >> 25) + 1) << 26);\r
+ if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;\r
\r
- requiredMem += 2*step;\r
- while (!testmem)\r
- {\r
- requiredMem -= step;\r
- testmem = malloc ((size_t)requiredMem);\r
- }\r
+ requiredMem += 2*step;\r
+ while (!testmem)\r
+ {\r
+ requiredMem -= step;\r
+ testmem = malloc ((size_t)requiredMem);\r
+ }\r
\r
- free (testmem);\r
- return (size_t) (requiredMem - step);\r
+ free (testmem);\r
+ return (size_t) (requiredMem - step);\r
}\r
\r
\r
static U64 BMK_GetFileSize(char* infilename)\r
{\r
- int r;\r
+ int r;\r
#if defined(_MSC_VER)\r
- struct _stat64 statbuf;\r
- r = _stat64(infilename, &statbuf);\r
+ struct _stat64 statbuf;\r
+ r = _stat64(infilename, &statbuf);\r
#else\r
- struct stat statbuf;\r
- r = stat(infilename, &statbuf);\r
+ struct stat statbuf;\r
+ r = stat(infilename, &statbuf);\r
#endif\r
- if (r || !S_ISREG(statbuf.st_mode)) return 0; // No good...\r
- return (U64)statbuf.st_size;\r
+ if (r || !S_ISREG(statbuf.st_mode)) return 0; // No good...\r
+ return (U64)statbuf.st_size;\r
}\r
\r
\r
// Loop for each file\r
while (fileIdx<nbFiles)\r
{\r
- // Check file existence\r
- infilename = fileNamesTable[fileIdx++];\r
- fileIn = fopen( infilename, "rb" );\r
- if (fileIn==NULL)\r
- {\r
- DISPLAY( "Pb opening %s\n", infilename);\r
- return 11;\r
- }\r
-\r
- // Memory allocation & restrictions\r
- largefilesize = BMK_GetFileSize(infilename);\r
- benchedSize = (size_t) BMK_findMaxMem(largefilesize) / 2;\r
- if ((U64)benchedSize > largefilesize) benchedSize = (size_t)largefilesize;\r
- if (benchedSize < largefilesize)\r
- {\r
- DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", infilename, (int)(benchedSize>>20));\r
- }\r
-\r
- // Alloc\r
- chunkP = (struct chunkParameters*) malloc(((benchedSize / chunkSize)+1) * sizeof(struct chunkParameters));\r
- orig_buff = malloc((size_t )benchedSize);\r
- nbChunks = (int) (benchedSize / chunkSize) + 1;\r
- maxCChunkSize = LZ4_compressBound(chunkSize);\r
- compressed_buff_size = nbChunks * maxCChunkSize;\r
- compressed_buff = malloc((size_t )compressed_buff_size);\r
-\r
-\r
- if(!orig_buff || !compressed_buff)\r
- {\r
- DISPLAY("\nError: not enough memory!\n");\r
- free(orig_buff);\r
- free(compressed_buff);\r
- fclose(fileIn);\r
- return 12;\r
- }\r
-\r
- // Init chunks data\r
- {\r
- int i;\r
- size_t remaining = benchedSize;\r
- char* in = orig_buff;\r
- char* out = compressed_buff;\r
- for (i=0; i<nbChunks; i++)\r
- {\r
- chunkP[i].id = i;\r
- chunkP[i].origBuffer = in; in += chunkSize;\r
- if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }\r
- chunkP[i].compressedBuffer = out; out += maxCChunkSize;\r
- chunkP[i].compressedSize = 0;\r
- }\r
- }\r
-\r
- // Fill input buffer\r
- DISPLAY("Loading %s... \r", infilename);\r
- readSize = fread(orig_buff, 1, benchedSize, fileIn);\r
- fclose(fileIn);\r
-\r
- if(readSize != benchedSize)\r
- {\r
- DISPLAY("\nError: problem reading file '%s' !! \n", infilename);\r
- free(orig_buff);\r
- free(compressed_buff);\r
- return 13;\r
- }\r
-\r
- // Calculating input Checksum\r
- crcc = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
-\r
-\r
- // Bench\r
- {\r
- int loopNb, nb_loops, chunkNb;\r
- size_t cSize=0;\r
- int milliTime;\r
- double fastestC = 100000000., fastestD = 100000000.;\r
- double ratio=0.;\r
-\r
- DISPLAY("\r%79s\r", "");\r
- for (loopNb = 1; loopNb <= nbIterations; loopNb++)\r
- {\r
- // Compression\r
- DISPLAY("%1i-%-14.14s : %9i ->\r", loopNb, infilename, (int)benchedSize);\r
- { size_t i; for (i=0; i<benchedSize; i++) compressed_buff[i]=(char)i; } // warmimg up memory\r
-\r
- nb_loops = 0;\r
- milliTime = BMK_GetMilliStart();\r
- while(BMK_GetMilliStart() == milliTime);\r
- milliTime = BMK_GetMilliStart();\r
- while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
- {\r
- for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
- chunkP[chunkNb].compressedSize = compP.compressionFunction(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);\r
- nb_loops++;\r
- }\r
- milliTime = BMK_GetMilliSpan(milliTime);\r
-\r
- if ((double)milliTime < fastestC*nb_loops) fastestC = (double)milliTime/nb_loops;\r
- cSize=0; for (chunkNb=0; chunkNb<nbChunks; chunkNb++) cSize += chunkP[chunkNb].compressedSize;\r
- ratio = (double)cSize/(double)benchedSize*100.;\r
-\r
- DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000.);\r
-\r
- // Decompression\r
- { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing area, for CRC checking\r
-\r
- nb_loops = 0;\r
- milliTime = BMK_GetMilliStart();\r
- while(BMK_GetMilliStart() == milliTime);\r
- milliTime = BMK_GetMilliStart();\r
- while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
- {\r
- for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
- chunkP[chunkNb].origSize = LZ4_decompress_safe(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
- //chunkP[chunkNb].compressedSize = LZ4_decompress_fast(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
- //chunkP[chunkNb].compressedSize = LZ4_decompress_fast_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
- //chunkP[chunkNb].origSize = LZ4_decompress_safe_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
- //chunkP[chunkNb].compressedSize = LZ4_uncompress(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
- //chunkP[chunkNb].origSize = LZ4_uncompress_unknownOutputSize(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
- nb_loops++;\r
- }\r
- milliTime = BMK_GetMilliSpan(milliTime);\r
-\r
- if ((double)milliTime < fastestD*nb_loops) fastestD = (double)milliTime/nb_loops;\r
- DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
-\r
- // CRC Checking\r
- crcd = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
- if (crcc!=crcd) { DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", infilename, (unsigned)crcc, (unsigned)crcd); break; }\r
- }\r
-\r
- if (crcc==crcd)\r
- {\r
- if (ratio<100.)\r
- DISPLAY("%-16.16s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
- else\r
- DISPLAY("%-16.16s : %9i -> %9i (%5.1f%%),%7.1f MB/s ,%7.1f MB/s \n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
- }\r
- totals += benchedSize;\r
- totalz += cSize;\r
- totalc += fastestC;\r
- totald += fastestD;\r
- }\r
-\r
- free(orig_buff);\r
- free(compressed_buff);\r
- free(chunkP);\r
+ // Check file existence\r
+ infilename = fileNamesTable[fileIdx++];\r
+ fileIn = fopen( infilename, "rb" );\r
+ if (fileIn==NULL)\r
+ {\r
+ DISPLAY( "Pb opening %s\n", infilename);\r
+ return 11;\r
+ }\r
+\r
+ // Memory allocation & restrictions\r
+ largefilesize = BMK_GetFileSize(infilename);\r
+ benchedSize = (size_t) BMK_findMaxMem(largefilesize) / 2;\r
+ if ((U64)benchedSize > largefilesize) benchedSize = (size_t)largefilesize;\r
+ if (benchedSize < largefilesize)\r
+ {\r
+ DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", infilename, (int)(benchedSize>>20));\r
+ }\r
+\r
+ // Alloc\r
+ chunkP = (struct chunkParameters*) malloc(((benchedSize / chunkSize)+1) * sizeof(struct chunkParameters));\r
+ orig_buff = malloc((size_t )benchedSize);\r
+ nbChunks = (int) (benchedSize / chunkSize) + 1;\r
+ maxCChunkSize = LZ4_compressBound(chunkSize);\r
+ compressed_buff_size = nbChunks * maxCChunkSize;\r
+ compressed_buff = malloc((size_t )compressed_buff_size);\r
+\r
+\r
+ if(!orig_buff || !compressed_buff)\r
+ {\r
+ DISPLAY("\nError: not enough memory!\n");\r
+ free(orig_buff);\r
+ free(compressed_buff);\r
+ fclose(fileIn);\r
+ return 12;\r
+ }\r
+\r
+ // Init chunks data\r
+ {\r
+ int i;\r
+ size_t remaining = benchedSize;\r
+ char* in = orig_buff;\r
+ char* out = compressed_buff;\r
+ for (i=0; i<nbChunks; i++)\r
+ {\r
+ chunkP[i].id = i;\r
+ chunkP[i].origBuffer = in; in += chunkSize;\r
+ if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }\r
+ chunkP[i].compressedBuffer = out; out += maxCChunkSize;\r
+ chunkP[i].compressedSize = 0;\r
+ }\r
+ }\r
+\r
+ // Fill input buffer\r
+ DISPLAY("Loading %s... \r", infilename);\r
+ readSize = fread(orig_buff, 1, benchedSize, fileIn);\r
+ fclose(fileIn);\r
+\r
+ if(readSize != benchedSize)\r
+ {\r
+ DISPLAY("\nError: problem reading file '%s' !! \n", infilename);\r
+ free(orig_buff);\r
+ free(compressed_buff);\r
+ return 13;\r
+ }\r
+\r
+ // Calculating input Checksum\r
+ crcc = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
+\r
+\r
+ // Bench\r
+ {\r
+ int loopNb, nb_loops, chunkNb;\r
+ size_t cSize=0;\r
+ int milliTime;\r
+ double fastestC = 100000000., fastestD = 100000000.;\r
+ double ratio=0.;\r
+\r
+ DISPLAY("\r%79s\r", "");\r
+ for (loopNb = 1; loopNb <= nbIterations; loopNb++)\r
+ {\r
+ // Compression\r
+ DISPLAY("%1i-%-14.14s : %9i ->\r", loopNb, infilename, (int)benchedSize);\r
+ { size_t i; for (i=0; i<benchedSize; i++) compressed_buff[i]=(char)i; } // warmimg up memory\r
+\r
+ nb_loops = 0;\r
+ milliTime = BMK_GetMilliStart();\r
+ while(BMK_GetMilliStart() == milliTime);\r
+ milliTime = BMK_GetMilliStart();\r
+ while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
+ {\r
+ for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
+ chunkP[chunkNb].compressedSize = compP.compressionFunction(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);\r
+ nb_loops++;\r
+ }\r
+ milliTime = BMK_GetMilliSpan(milliTime);\r
+\r
+ if ((double)milliTime < fastestC*nb_loops) fastestC = (double)milliTime/nb_loops;\r
+ cSize=0; for (chunkNb=0; chunkNb<nbChunks; chunkNb++) cSize += chunkP[chunkNb].compressedSize;\r
+ ratio = (double)cSize/(double)benchedSize*100.;\r
+\r
+ DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000.);\r
+\r
+ // Decompression\r
+ { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; } // zeroing area, for CRC checking\r
+\r
+ nb_loops = 0;\r
+ milliTime = BMK_GetMilliStart();\r
+ while(BMK_GetMilliStart() == milliTime);\r
+ milliTime = BMK_GetMilliStart();\r
+ while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
+ {\r
+ for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
+ chunkP[chunkNb].origSize = LZ4_decompress_safe(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+ //chunkP[chunkNb].compressedSize = LZ4_decompress_fast(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+ //chunkP[chunkNb].compressedSize = LZ4_decompress_fast_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+ //chunkP[chunkNb].origSize = LZ4_decompress_safe_withPrefix64k(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+ //chunkP[chunkNb].compressedSize = LZ4_uncompress(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].origSize);\r
+ //chunkP[chunkNb].origSize = LZ4_uncompress_unknownOutputSize(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkSize);\r
+ nb_loops++;\r
+ }\r
+ milliTime = BMK_GetMilliSpan(milliTime);\r
+\r
+ if ((double)milliTime < fastestD*nb_loops) fastestD = (double)milliTime/nb_loops;\r
+ DISPLAY("%1i-%-14.14s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\r", loopNb, infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+\r
+ // CRC Checking\r
+ crcd = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
+ if (crcc!=crcd) { DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", infilename, (unsigned)crcc, (unsigned)crcd); break; }\r
+ }\r
+\r
+ if (crcc==crcd)\r
+ {\r
+ if (ratio<100.)\r
+ DISPLAY("%-16.16s : %9i -> %9i (%5.2f%%),%7.1f MB/s ,%7.1f MB/s\n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+ else\r
+ DISPLAY("%-16.16s : %9i -> %9i (%5.1f%%),%7.1f MB/s ,%7.1f MB/s \n", infilename, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / fastestC / 1000., (double)benchedSize / fastestD / 1000.);\r
+ }\r
+ totals += benchedSize;\r
+ totalz += cSize;\r
+ totalc += fastestC;\r
+ totald += fastestD;\r
+ }\r
+\r
+ free(orig_buff);\r
+ free(compressed_buff);\r
+ free(chunkP);\r
}\r
\r
if (nbFiles > 1)\r
- printf("%-16.16s :%10llu ->%10llu (%5.2f%%), %6.1f MB/s , %6.1f MB/s\n", " TOTAL", (long long unsigned int)totals, (long long unsigned int)totalz, (double)totalz/(double)totals*100., (double)totals/totalc/1000., (double)totals/totald/1000.);\r
+ printf("%-16.16s :%10llu ->%10llu (%5.2f%%), %6.1f MB/s , %6.1f MB/s\n", " TOTAL", (long long unsigned int)totals, (long long unsigned int)totalz, (double)totalz/(double)totals*100., (double)totals/totalc/1000., (double)totals/totald/1000.);\r
\r
if (BMK_pause) { printf("press enter...\n"); getchar(); }\r
\r
#define MEMORY_USAGE 14\r
\r
// HEAPMODE :\r
-// Select if compression algorithm will allocate space for its tables\r
+// Select how default compression function will allocate memory for its hash table,\r
// in memory stack (0:default, fastest), or in memory heap (1:requires memory allocation (malloc)).\r
// Default allocation strategy is to use stack (HEAPMODE 0)\r
+// Note : explicit functions *_stack* and *_heap* are unaffected by this setting\r
#define HEAPMODE 0\r
\r
// BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE :\r
// CPU Feature Detection\r
//**************************************\r
// 32 or 64 bits ?\r
-#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) ) // Detects 64 bits mode\r
+#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) \\r
+ || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) \\r
+ || defined(__ia64__) ) // Detects 64 bits mode\r
# define LZ4_ARCH64 1\r
#else\r
# define LZ4_ARCH64 0\r
//**************************************\r
// Compiler Options\r
//**************************************\r
-#if __STDC_VERSION__ >= 199901L // C99\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
/* "restrict" is a known keyword */\r
#else\r
# define restrict // Disable restrict\r
//**************************************\r
// Basic Types\r
//**************************************\r
-#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively\r
-# define BYTE unsigned __int8\r
-# define U16 unsigned __int16\r
-# define U32 unsigned __int32\r
-# define S32 __int32\r
-# define U64 unsigned __int64\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
+# include <stdint.h>\r
+ typedef uint8_t BYTE;\r
+ typedef uint16_t U16;\r
+ typedef uint32_t U32;\r
+ typedef int32_t S32;\r
+ typedef uint64_t U64;\r
#else\r
-# include <stdint.h>\r
-# define BYTE uint8_t\r
-# define U16 uint16_t\r
-# define U32 uint32_t\r
-# define S32 int32_t\r
-# define U64 uint64_t\r
+ typedef unsigned char BYTE;\r
+ typedef unsigned short U16;\r
+ typedef unsigned int U32;\r
+ typedef signed int S32;\r
+ typedef unsigned long long U64;\r
#endif\r
\r
-#ifndef LZ4_FORCE_UNALIGNED_ACCESS\r
+#if defined(__GNUC__) && !defined(LZ4_FORCE_UNALIGNED_ACCESS)\r
+# define _PACKED __attribute__ ((packed))\r
+#else\r
+# define _PACKED\r
+#endif\r
+\r
+#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)\r
# pragma pack(push, 1)\r
#endif\r
\r
-typedef struct _U16_S { U16 v; } U16_S;\r
-typedef struct _U32_S { U32 v; } U32_S;\r
-typedef struct _U64_S { U64 v; } U64_S;\r
+typedef struct _U16_S { U16 v; } _PACKED U16_S;\r
+typedef struct _U32_S { U32 v; } _PACKED U32_S;\r
+typedef struct _U64_S { U64 v; } _PACKED U64_S;\r
\r
-#ifndef LZ4_FORCE_UNALIGNED_ACCESS\r
+#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)\r
# pragma pack(pop)\r
#endif\r
\r
//**************************************\r
// Macros\r
//**************************************\r
-#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d<e);\r
-#define LZ4_BLINDCOPY(s,d,l) { BYTE* e=(d)+l; LZ4_WILDCOPY(s,d,e); d=e; }\r
+#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d<e);\r
+#define LZ4_BLINDCOPY(s,d,l) { BYTE* e=(d)+(l); LZ4_WILDCOPY(s,d,e); d=e; }\r
\r
\r
//****************************\r
length = (int)(ip - anchor);\r
token = op++;\r
#ifdef LIMITED_OUTPUT\r
- if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit\r
+ if unlikely(op + length + (2 + 1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit\r
#endif\r
-#ifdef _MSC_VER\r
if (length>=(int)RUN_MASK) \r
{ \r
int len = length-RUN_MASK; \r
*token=(RUN_MASK<<ML_BITS); \r
- if (len>254)\r
- {\r
- do { *op++ = 255; len -= 255; } while (len>254);\r
- *op++ = (BYTE)len; \r
- memcpy(op, anchor, length);\r
- op += length;\r
- goto _next_match;\r
- }\r
- else\r
+ for(; len >= 255 ; len-=255) *op++ = 255; \r
*op++ = (BYTE)len; \r
}\r
else *token = (BYTE)(length<<ML_BITS);\r
-#else\r
- if (length>=(int)RUN_MASK) \r
- { \r
- int len;\r
- *token=(RUN_MASK<<ML_BITS); \r
- len = length-RUN_MASK; \r
- for(; len > 254 ; len-=255) *op++ = 255; \r
- *op++ = (BYTE)len; \r
- }\r
- else *token = (length<<ML_BITS);\r
-#endif\r
\r
// Copy Literals\r
LZ4_BLINDCOPY(anchor, op, length);\r
// Encode MatchLength\r
length = (int)(ip - anchor);\r
#ifdef LIMITED_OUTPUT\r
- if unlikely(op + (1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit\r
+ if unlikely(op + (1 + LASTLITERALS) + (length>>8) > oend) return 0; // Check output limit\r
#endif\r
if (length>=(int)ML_MASK) \r
{ \r
*token += ML_MASK; \r
length -= ML_MASK; \r
for (; length > 509 ; length-=510) { *op++ = 255; *op++ = 255; } \r
- if (length > 254) { length-=255; *op++ = 255; } \r
+ if (length >= 255) { length-=255; *op++ = 255; } \r
*op++ = (BYTE)length; \r
}\r
else *token += (BYTE)length;\r
#ifdef LIMITED_OUTPUT\r
if (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) return 0; // Check output limit\r
#endif\r
- if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\r
+ if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun >= 255 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\r
else *op++ = (BYTE)(lastRun<<ML_BITS);\r
memcpy(op, anchor, iend - anchor);\r
op += iend-anchor;\r
/*\r
Note : this is stand-alone program.\r
It is not part of LZ4 compression library, it is a user program of LZ4 library.\r
- The license of LZ4 is BSD.\r
- The license of xxHash is BSD.\r
- The license of the compression program is GPLv2.\r
+ The license of LZ4 library is BSD.\r
+ The license of xxHash library is BSD.\r
+ The license of this compression CLI program is GPLv2.\r
*/\r
\r
//**************************************\r
int usage(char* exename)\r
{\r
DISPLAY( "Usage :\n");\r
- DISPLAY( " %s [arg] input output\n", exename);\r
+ DISPLAY( " %s [arg] input [output]\n", exename);\r
DISPLAY( "Arguments :\n");\r
DISPLAY( " -c0/-c : Fast compression (default) \n");\r
DISPLAY( " -c1/-hc: High compression \n");\r
// No output filename ==> build one automatically (for compression only)\r
if (!output_filename) \r
{ \r
- if (!decode)\r
+ if (!decode) // compression\r
{\r
int i=0, l=0;\r
while (input_filename[l]!=0) l++;\r
}\r
else\r
{\r
- badusage(exename); \r
- return 1; \r
+ int inl=0,outl;\r
+ while (input_filename[inl]!=0) inl++;\r
+ output_filename = (char*)calloc(1,inl+1);\r
+ for (outl=0;outl<inl;outl++) output_filename[outl] = input_filename[outl];\r
+ if (inl>4)\r
+ while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) output_filename[outl--]=0;\r
+ if (outl != inl-5) output_filename = NULL;\r
}\r
+ if (!output_filename) { badusage(exename); return 1; }\r
}\r
\r
if (decode) return decodeFile(input_filename, output_filename);\r
\r
\r
//**************************************\r
+// Memory routines\r
+//**************************************\r
+#include <stdlib.h> // calloc, free\r
+#define ALLOCATOR(s) calloc(1,s)\r
+#define FREEMEM free\r
+#include <string.h> // memset, memcpy\r
+#define MEM_INIT memset\r
+\r
+\r
+//**************************************\r
// CPU Feature Detection\r
//**************************************\r
// 32 or 64 bits ?\r
-#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) ) // Detects 64 bits mode\r
+#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) \\r
+ || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) \\r
+ || defined(__ia64__) ) // Detects 64 bits mode\r
# define LZ4_ARCH64 1\r
#else\r
# define LZ4_ARCH64 0\r
//**************************************\r
// Compiler Options\r
//**************************************\r
-#if __STDC_VERSION__ >= 199901L // C99\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
/* "restrict" is a known keyword */\r
#else\r
# define restrict // Disable restrict\r
//**************************************\r
// Includes\r
//**************************************\r
-#include <stdlib.h> // calloc, free\r
-#include <string.h> // memset, memcpy\r
#include "lz4hc.h"\r
#include "lz4.h"\r
\r
-#define ALLOCATOR(s) calloc(1,s)\r
-#define FREEMEM free\r
-#define MEM_INIT memset\r
-\r
\r
//**************************************\r
// Basic Types\r
//**************************************\r
-#if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively\r
-#define BYTE unsigned __int8\r
-#define U16 unsigned __int16\r
-#define U32 unsigned __int32\r
-#define S32 __int32\r
-#define U64 unsigned __int64\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
+# include <stdint.h>\r
+ typedef uint8_t BYTE;\r
+ typedef uint16_t U16;\r
+ typedef uint32_t U32;\r
+ typedef int32_t S32;\r
+ typedef uint64_t U64;\r
+#else\r
+ typedef unsigned char BYTE;\r
+ typedef unsigned short U16;\r
+ typedef unsigned int U32;\r
+ typedef signed int S32;\r
+ typedef unsigned long long U64;\r
+#endif\r
+\r
+#if defined(__GNUC__) && !defined(LZ4_FORCE_UNALIGNED_ACCESS)\r
+# define _PACKED __attribute__ ((packed))\r
#else\r
-#include <stdint.h>\r
-#define BYTE uint8_t\r
-#define U16 uint16_t\r
-#define U32 uint32_t\r
-#define S32 int32_t\r
-#define U64 uint64_t\r
+# define _PACKED\r
#endif\r
\r
-#ifndef LZ4_FORCE_UNALIGNED_ACCESS\r
-#pragma pack(push, 1) \r
+#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)\r
+# pragma pack(push, 1)\r
#endif\r
\r
-typedef struct _U16_S { U16 v; } U16_S;\r
-typedef struct _U32_S { U32 v; } U32_S;\r
-typedef struct _U64_S { U64 v; } U64_S;\r
+typedef struct _U16_S { U16 v; } _PACKED U16_S;\r
+typedef struct _U32_S { U32 v; } _PACKED U32_S;\r
+typedef struct _U64_S { U64 v; } _PACKED U64_S;\r
\r
-#ifndef LZ4_FORCE_UNALIGNED_ACCESS\r
-#pragma pack(pop) \r
+#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)\r
+# pragma pack(pop)\r
#endif\r
\r
#define A64(x) (((U64_S *)(x))->v)\r
//**************************************\r
// Architecture-specific macros\r
//**************************************\r
-#if LZ4_ARCH64 // 64-bit\r
-#define STEPSIZE 8\r
-#define LZ4_COPYSTEP(s,d) A64(d) = A64(s); d+=8; s+=8;\r
-#define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d)\r
-#define UARCH U64\r
-#define AARCH A64\r
-#define HTYPE U32\r
-#define INITBASE(b,s) const BYTE* const b = s\r
-#else // 32-bit\r
-#define STEPSIZE 4\r
-#define LZ4_COPYSTEP(s,d) A32(d) = A32(s); d+=4; s+=4;\r
-#define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);\r
-#define UARCH U32\r
-#define AARCH A32\r
-#define HTYPE const BYTE*\r
-#define INITBASE(b,s) const int b = 0\r
+#if LZ4_ARCH64 // 64-bit\r
+# define STEPSIZE 8\r
+# define LZ4_COPYSTEP(s,d) A64(d) = A64(s); d+=8; s+=8;\r
+# define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d)\r
+# define UARCH U64\r
+# define AARCH A64\r
+# define HTYPE U32\r
+# define INITBASE(b,s) const BYTE* const b = s\r
+#else // 32-bit\r
+# define STEPSIZE 4\r
+# define LZ4_COPYSTEP(s,d) A32(d) = A32(s); d+=4; s+=4;\r
+# define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);\r
+# define UARCH U32\r
+# define AARCH A32\r
+# define HTYPE const BYTE*\r
+# define INITBASE(b,s) const int b = 0\r
#endif\r
\r
#if defined(LZ4_BIG_ENDIAN)\r
-#define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }\r
-#define LZ4_WRITE_LITTLEENDIAN_16(p,i) { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }\r
-#else // Little Endian\r
-#define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }\r
-#define LZ4_WRITE_LITTLEENDIAN_16(p,v) { A16(p) = v; p+=2; }\r
+# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }\r
+# define LZ4_WRITE_LITTLEENDIAN_16(p,i) { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }\r
+#else // Little Endian\r
+# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }\r
+# define LZ4_WRITE_LITTLEENDIAN_16(p,v) { A16(p) = v; p+=2; }\r
#endif\r
\r
\r
//**************************************\r
#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d<e);\r
#define LZ4_BLINDCOPY(s,d,l) { BYTE* e=d+l; LZ4_WILDCOPY(s,d,e); d=e; }\r
-#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))\r
-#define HASH_VALUE(p) HASH_FUNCTION(A32(p))\r
-#define HASH_POINTER(p) (HashTable[HASH_VALUE(p)] + base)\r
-#define DELTANEXT(p) chainTable[(size_t)(p) & MAXD_MASK] \r
-#define GETNEXT(p) ((p) - (size_t)DELTANEXT(p))\r
+#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))\r
+#define HASH_VALUE(p) HASH_FUNCTION(A32(p))\r
+#define HASH_POINTER(p) (HashTable[HASH_VALUE(p)] + base)\r
+#define DELTANEXT(p) chainTable[(size_t)(p) & MAXD_MASK] \r
+#define GETNEXT(p) ((p) - (size_t)DELTANEXT(p))\r
\r
\r
//**************************************\r
inline static int LZ4_NbCommonBytes (register U64 val)\r
{\r
#if defined(LZ4_BIG_ENDIAN)\r
- #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
unsigned long r = 0;\r
_BitScanReverse64( &r, val );\r
return (int)(r>>3);\r
- #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
return (__builtin_clzll(val) >> 3); \r
- #else\r
+# else\r
int r;\r
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }\r
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }\r
r += (!val);\r
return r;\r
- #endif\r
+# endif\r
#else\r
- #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
unsigned long r = 0;\r
_BitScanForward64( &r, val );\r
return (int)(r>>3);\r
- #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
return (__builtin_ctzll(val) >> 3); \r
- #else\r
+# else\r
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };\r
return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58];\r
- #endif\r
+# endif\r
#endif\r
}\r
\r
inline static int LZ4_NbCommonBytes (register U32 val)\r
{\r
#if defined(LZ4_BIG_ENDIAN)\r
- #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
unsigned long r;\r
_BitScanReverse( &r, val );\r
return (int)(r>>3);\r
- #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
return (__builtin_clz(val) >> 3); \r
- #else\r
+# else\r
int r;\r
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }\r
r += (!val);\r
return r;\r
- #endif\r
+# endif\r
#else\r
- #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
unsigned long r;\r
_BitScanForward( &r, val );\r
return (int)(r>>3);\r
- #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
+# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)\r
return (__builtin_ctz(val) >> 3); \r
- #else\r
+# else\r
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };\r
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];\r
- #endif\r
+# endif\r
#endif\r
}\r
\r
\r
// Locally Generated\r
#undef ENCODE_SEQUENCE\r
+#undef ENCODE_SEQUENCE_NAME\r
\r
// Optional defines\r
#ifdef LIMITED_OUTPUT\r
/*\r
- xxHash - Fast Hash algorithm\r
- Copyright (C) 2012-2013, Yann Collet.\r
- BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\r
-\r
- Redistribution and use in source and binary forms, with or without\r
- modification, are permitted provided that the following conditions are\r
- met:\r
-\r
- * Redistributions of source code must retain the above copyright\r
- notice, this list of conditions and the following disclaimer.\r
- * Redistributions in binary form must reproduce the above\r
- copyright notice, this list of conditions and the following disclaimer\r
- in the documentation and/or other materials provided with the\r
- distribution.\r
-\r
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-\r
- You can contact the author at :\r
- - xxHash source repository : http://code.google.com/p/xxhash/\r
+xxHash - Fast Hash algorithm\r
+Copyright (C) 2012-2013, Yann Collet.\r
+BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions are\r
+met:\r
+\r
+* Redistributions of source code must retain the above copyright\r
+notice, this list of conditions and the following disclaimer.\r
+* Redistributions in binary form must reproduce the above\r
+copyright notice, this list of conditions and the following disclaimer\r
+in the documentation and/or other materials provided with the\r
+distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+You can contact the author at :\r
+- xxHash source repository : http://code.google.com/p/xxhash/\r
*/\r
\r
\r
//**************************************\r
// Tuning parameters\r
//**************************************\r
-// FORCE_NATIVE_FORMAT :\r
-// By default, xxHash library provides endian-independant Hash values.\r
-// Results are therefore identical for big-endian and little-endian CPU.\r
+// XXH_ACCEPT_NULL_INPUT_POINTER :\r
+// If the input pointer is a null pointer, xxHash default behavior is to crash, since it is a bad input.\r
+// If this option is enabled, xxHash output for null input pointers will be the same as a null-length input.\r
+// This option has a very small performance cost (only measurable on small inputs).\r
+// By default, this option is disabled. To enable it, uncomment below define :\r
+//#define XXH_ACCEPT_NULL_INPUT_POINTER 1\r
+\r
+// XXH_FORCE_NATIVE_FORMAT :\r
+// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.\r
+// Results are therefore identical for little-endian and big-endian CPU.\r
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.\r
// Should endian-independance be of no importance to your application, you may uncomment the #define below\r
// It will improve speed for Big-endian CPU.\r
// This option has no impact on Little_Endian CPU.\r
-//#define FORCE_NATIVE_FORMAT 1\r
+//#define XXH_FORCE_NATIVE_FORMAT 1\r
\r
\r
\r
//**************************************\r
// Little Endian or Big Endian ?\r
// You can overwrite the #define below if you know your architecture endianess\r
-#if defined(FORCE_NATIVE_FORMAT) && (FORCE_NATIVE_FORMAT==1)\r
+#if defined(XXH_FORCE_NATIVE_FORMAT) && (XXH_FORCE_NATIVE_FORMAT==1)\r
// Force native format. The result will be endian dependant.\r
# define XXH_BIG_ENDIAN 0\r
#elif defined (__GLIBC__)\r
#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))\r
# define XXH_BIG_ENDIAN 1\r
#elif defined(__sparc) || defined(__sparc__) \\r
- || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \\r
- || defined(__hpux) || defined(__hppa) \\r
- || defined(_MIPSEB) || defined(__s390__)\r
+ || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \\r
+ || defined(__hpux) || defined(__hppa) \\r
+ || defined(_MIPSEB) || defined(__s390__)\r
# define XXH_BIG_ENDIAN 1\r
#endif\r
\r
#endif\r
\r
\r
+//**************************************\r
+// Basic Types\r
+//**************************************\r
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99\r
+# include <stdint.h>\r
+ typedef uint8_t BYTE;\r
+ typedef uint16_t U16;\r
+ typedef uint32_t U32;\r
+ typedef int32_t S32;\r
+ typedef uint64_t U64;\r
+#else\r
+ typedef unsigned char BYTE;\r
+ typedef unsigned short U16;\r
+ typedef unsigned int U32;\r
+ typedef signed int S32;\r
+ typedef unsigned long long U64;\r
+#endif\r
+\r
\r
//**************************************\r
// Compiler-specific Options & Functions\r
#elif GCC_VERSION >= 403\r
# define XXH_swap32 __builtin_bswap32\r
#else\r
-static inline unsigned int XXH_swap32 (unsigned int x) {\r
- return ((x << 24) & 0xff000000 ) |\r
- ((x << 8) & 0x00ff0000 ) |\r
- ((x >> 8) & 0x0000ff00 ) |\r
- ((x >> 24) & 0x000000ff );\r
- }\r
+static inline U32 XXH_swap32 (U32 x) {\r
+ return ((x << 24) & 0xff000000 ) |\r
+ ((x << 8) & 0x00ff0000 ) |\r
+ ((x >> 8) & 0x0000ff00 ) |\r
+ ((x >> 24) & 0x000000ff );}\r
#endif\r
\r
\r
-\r
//**************************************\r
// Constants\r
//**************************************\r
#define PRIME32_5 374761393U\r
\r
\r
-\r
//**************************************\r
// Macros\r
//**************************************\r
-#define XXH_LE32(p) (XXH_BIG_ENDIAN ? XXH_swap32(*(unsigned int*)(p)) : *(unsigned int*)(p))\r
+#define XXH_LE32(p) (XXH_BIG_ENDIAN ? XXH_swap32(*(U32*)(p)) : *(U32*)(p))\r
\r
\r
\r
// Simple Hash Functions\r
//****************************\r
\r
-unsigned int XXH32(const void* input, int len, unsigned int seed)\r
+U32 XXH32(const void* input, int len, U32 seed)\r
{\r
#if 0\r
- // Simple version, good for code maintenance, but unfortunately slow for small inputs\r
- void* state = XXH32_init(seed);\r
- XXH32_update(state, input, len);\r
- return XXH32_digest(state);\r
+ // Simple version, good for code maintenance, but unfortunately slow for small inputs\r
+ void* state = XXH32_init(seed);\r
+ XXH32_update(state, input, len);\r
+ return XXH32_digest(state);\r
#else\r
\r
- const unsigned char* p = (const unsigned char*)input;\r
- const unsigned char* const bEnd = p + len;\r
- unsigned int h32;\r
-\r
- if (len>=16)\r
- {\r
- const unsigned char* const limit = bEnd - 16;\r
- unsigned int v1 = seed + PRIME32_1 + PRIME32_2;\r
- unsigned int v2 = seed + PRIME32_2;\r
- unsigned int v3 = seed + 0;\r
- unsigned int v4 = seed - PRIME32_1;\r
-\r
- do\r
- {\r
- v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;\r
- v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;\r
- v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;\r
- v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;\r
- } while (p<=limit) ;\r
-\r
- h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);\r
- }\r
- else\r
- {\r
- h32 = seed + PRIME32_5;\r
- }\r
-\r
- h32 += (unsigned int) len;\r
- \r
- while (p<=bEnd-4)\r
- {\r
- h32 += XXH_LE32(p) * PRIME32_3;\r
- h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;\r
- p+=4;\r
- }\r
-\r
- while (p<bEnd)\r
- {\r
- h32 += (*p) * PRIME32_5;\r
- h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;\r
- p++;\r
- }\r
-\r
- h32 ^= h32 >> 15;\r
- h32 *= PRIME32_2;\r
- h32 ^= h32 >> 13;\r
- h32 *= PRIME32_3;\r
- h32 ^= h32 >> 16;\r
-\r
- return h32;\r
+ const BYTE* p = (const BYTE*)input;\r
+ const BYTE* const bEnd = p + len;\r
+ U32 h32;\r
+\r
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER\r
+ if (p==NULL) { len=0; p=(const BYTE*)16; }\r
+#endif\r
+\r
+ if (len>=16)\r
+ {\r
+ const BYTE* const limit = bEnd - 16;\r
+ U32 v1 = seed + PRIME32_1 + PRIME32_2;\r
+ U32 v2 = seed + PRIME32_2;\r
+ U32 v3 = seed + 0;\r
+ U32 v4 = seed - PRIME32_1;\r
+\r
+ do\r
+ {\r
+ v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;\r
+ v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;\r
+ v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;\r
+ v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;\r
+ } while (p<=limit);\r
+\r
+ h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);\r
+ }\r
+ else\r
+ {\r
+ h32 = seed + PRIME32_5;\r
+ }\r
+\r
+ h32 += (U32) len;\r
+\r
+ while (p<=bEnd-4)\r
+ {\r
+ h32 += XXH_LE32(p) * PRIME32_3;\r
+ h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;\r
+ p+=4;\r
+ }\r
+\r
+ while (p<bEnd)\r
+ {\r
+ h32 += (*p) * PRIME32_5;\r
+ h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;\r
+ p++;\r
+ }\r
+\r
+ h32 ^= h32 >> 15;\r
+ h32 *= PRIME32_2;\r
+ h32 ^= h32 >> 13;\r
+ h32 *= PRIME32_3;\r
+ h32 ^= h32 >> 16;\r
+\r
+ return h32;\r
\r
#endif\r
}\r
\r
struct XXH_state32_t\r
{\r
- unsigned int seed;\r
- unsigned int v1;\r
- unsigned int v2;\r
- unsigned int v3;\r
- unsigned int v4;\r
- unsigned long long total_len;\r
- char memory[16];\r
- int memsize;\r
+ U32 seed;\r
+ U32 v1;\r
+ U32 v2;\r
+ U32 v3;\r
+ U32 v4;\r
+ U64 total_len;\r
+ char memory[16];\r
+ int memsize;\r
};\r
\r
\r
-void* XXH32_init (unsigned int seed)\r
+int XXH32_sizeofState() { return sizeof(struct XXH_state32_t); }\r
+\r
+\r
+XXH_errorcode XXH32_resetState(void* state_in, unsigned int seed)\r
+{ \r
+ struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;\r
+ state->seed = seed;\r
+ state->v1 = seed + PRIME32_1 + PRIME32_2;\r
+ state->v2 = seed + PRIME32_2;\r
+ state->v3 = seed + 0;\r
+ state->v4 = seed - PRIME32_1;\r
+ state->total_len = 0;\r
+ state->memsize = 0;\r
+ return OK;\r
+}\r
+\r
+\r
+void* XXH32_init (U32 seed)\r
{\r
- struct XXH_state32_t * state = (struct XXH_state32_t *) malloc ( sizeof(struct XXH_state32_t));\r
- state->seed = seed;\r
- state->v1 = seed + PRIME32_1 + PRIME32_2;\r
- state->v2 = seed + PRIME32_2;\r
- state->v3 = seed + 0;\r
- state->v4 = seed - PRIME32_1;\r
- state->total_len = 0;\r
- state->memsize = 0;\r
-\r
- return (void*)state;\r
+ struct XXH_state32_t * state = (struct XXH_state32_t *) malloc (sizeof(struct XXH_state32_t));\r
+ XXH32_resetState(state, seed);\r
+ return (void*)state;\r
}\r
\r
\r
XXH_errorcode XXH32_update (void* state_in, const void* input, int len)\r
{\r
- struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;\r
- const unsigned char* p = (const unsigned char*)input;\r
- const unsigned char* const bEnd = p + len;\r
+ struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;\r
+ const BYTE* p = (const BYTE*)input;\r
+ const BYTE* const bEnd = p + len;\r
+\r
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER\r
+ if (input==NULL) return XXH_ERROR;\r
+#endif\r
\r
- if (input==NULL) return XXH_ERROR;\r
- \r
state->total_len += len;\r
- \r
- if (state->memsize + len < 16) // fill in tmp buffer\r
- {\r
- memcpy(state->memory + state->memsize, input, len);\r
- state->memsize += len;\r
- return OK;\r
- }\r
-\r
- if (state->memsize) // some data left from previous update\r
- {\r
- memcpy(state->memory + state->memsize, input, 16-state->memsize);\r
- {\r
- const unsigned int* p32 = (const unsigned int*)state->memory;\r
- state->v1 += XXH_LE32(p32) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;\r
- state->v2 += XXH_LE32(p32) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; \r
- state->v3 += XXH_LE32(p32) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;\r
- state->v4 += XXH_LE32(p32) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;\r
- }\r
- p += 16-state->memsize;\r
- state->memsize = 0;\r
- }\r
-\r
- {\r
- const unsigned char* const limit = bEnd - 16;\r
- unsigned int v1 = state->v1;\r
- unsigned int v2 = state->v2;\r
- unsigned int v3 = state->v3;\r
- unsigned int v4 = state->v4;\r
-\r
- while (p<=limit)\r
- {\r
- v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;\r
- v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;\r
- v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;\r
- v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;\r
- } \r
-\r
- state->v1 = v1;\r
- state->v2 = v2;\r
- state->v3 = v3;\r
- state->v4 = v4;\r
- }\r
-\r
- if (p < bEnd)\r
- {\r
- memcpy(state->memory, p, bEnd-p);\r
- state->memsize = (int)(bEnd-p);\r
- }\r
-\r
- return OK;\r
+\r
+ if (state->memsize + len < 16) // fill in tmp buffer\r
+ {\r
+ memcpy(state->memory + state->memsize, input, len);\r
+ state->memsize += len;\r
+ return OK;\r
+ }\r
+\r
+ if (state->memsize) // some data left from previous update\r
+ {\r
+ memcpy(state->memory + state->memsize, input, 16-state->memsize);\r
+ {\r
+ const U32* p32 = (const U32*)state->memory;\r
+ state->v1 += XXH_LE32(p32) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;\r
+ state->v2 += XXH_LE32(p32) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; \r
+ state->v3 += XXH_LE32(p32) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;\r
+ state->v4 += XXH_LE32(p32) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;\r
+ }\r
+ p += 16-state->memsize;\r
+ state->memsize = 0;\r
+ }\r
+\r
+ if (p <= bEnd-16)\r
+ {\r
+ const BYTE* const limit = bEnd - 16;\r
+ U32 v1 = state->v1;\r
+ U32 v2 = state->v2;\r
+ U32 v3 = state->v3;\r
+ U32 v4 = state->v4;\r
+\r
+ do\r
+ {\r
+ v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;\r
+ v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;\r
+ v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;\r
+ v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;\r
+ } while (p<=limit);\r
+\r
+ state->v1 = v1;\r
+ state->v2 = v2;\r
+ state->v3 = v3;\r
+ state->v4 = v4;\r
+ }\r
+\r
+ if (p < bEnd)\r
+ {\r
+ memcpy(state->memory, p, bEnd-p);\r
+ state->memsize = (int)(bEnd-p);\r
+ }\r
+\r
+ return OK;\r
}\r
\r
\r
-unsigned int XXH32_intermediateDigest (void* state_in)\r
+U32 XXH32_intermediateDigest (void* state_in)\r
{\r
- struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;\r
- unsigned char * p = (unsigned char*)state->memory;\r
- unsigned char* bEnd = (unsigned char*)state->memory + state->memsize;\r
- unsigned int h32;\r
-\r
-\r
- if (state->total_len >= 16)\r
- {\r
- h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);\r
- }\r
- else\r
- {\r
- h32 = state->seed + PRIME32_5;\r
- }\r
-\r
- h32 += (unsigned int) state->total_len;\r
- \r
- while (p<=bEnd-4)\r
- {\r
- h32 += XXH_LE32(p) * PRIME32_3;\r
- h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;\r
- p+=4;\r
- }\r
-\r
- while (p<bEnd)\r
- {\r
- h32 += (*p) * PRIME32_5;\r
- h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;\r
- p++;\r
- }\r
-\r
- h32 ^= h32 >> 15;\r
- h32 *= PRIME32_2;\r
- h32 ^= h32 >> 13;\r
- h32 *= PRIME32_3;\r
- h32 ^= h32 >> 16;\r
-\r
- return h32;\r
+ struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;\r
+ BYTE * p = (BYTE*)state->memory;\r
+ BYTE* bEnd = (BYTE*)state->memory + state->memsize;\r
+ U32 h32;\r
+\r
+\r
+ if (state->total_len >= 16)\r
+ {\r
+ h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);\r
+ }\r
+ else\r
+ {\r
+ h32 = state->seed + PRIME32_5;\r
+ }\r
+\r
+ h32 += (U32) state->total_len;\r
+\r
+ while (p<=bEnd-4)\r
+ {\r
+ h32 += XXH_LE32(p) * PRIME32_3;\r
+ h32 = XXH_rotl32(h32, 17) * PRIME32_4;\r
+ p+=4;\r
+ }\r
+\r
+ while (p<bEnd)\r
+ {\r
+ h32 += (*p) * PRIME32_5;\r
+ h32 = XXH_rotl32(h32, 11) * PRIME32_1;\r
+ p++;\r
+ }\r
+\r
+ h32 ^= h32 >> 15;\r
+ h32 *= PRIME32_2;\r
+ h32 ^= h32 >> 13;\r
+ h32 *= PRIME32_3;\r
+ h32 ^= h32 >> 16;\r
+\r
+ return h32;\r
}\r
\r
\r
-unsigned int XXH32_digest (void* state_in)\r
+U32 XXH32_digest (void* state_in)\r
{\r
- unsigned int h32 = XXH32_intermediateDigest(state_in);\r
+ U32 h32 = XXH32_intermediateDigest(state_in);\r
\r
- free(state_in);\r
+ free(state_in);\r
\r
- return h32;\r
+ return h32;\r
}\r
*/\r
\r
\r
+int XXH32_sizeofState();\r
+XXH_errorcode XXH32_resetState(void* state_in, unsigned int seed);\r
+/*\r
+These functions are the basic elements of XXH32_init();\r
+The objective is to allow user application to make its own allocation.\r
+\r
+XXH32_sizeofState() is used to know how much space must be allocated by the application.\r
+This space must be referenced by a void* pointer.\r
+This pointer must be provided as 'state_in' into XXH32_resetState(), which initializes the state.\r
+*/\r
+\r
+\r
unsigned int XXH32_intermediateDigest (void* state);\r
/*\r
This function does the same as XXH32_digest(), generating a 32-bit hash,\r