const BYTE* hashTable[HASHTABLESIZE];\r
};\r
\r
+#ifdef __GNUC__\r
+# define _PACKED __attribute__ ((packed))\r
+#else\r
+# define _PACKED\r
+#endif\r
+\r
+typedef struct _U32_S\r
+{\r
+ U32 v;\r
+} _PACKED U32_S;\r
+\r
+typedef struct _U16_S\r
+{\r
+ U16 v;\r
+} _PACKED U16_S;\r
+\r
+#define A32(x) (((U32_S *)(x))->v)\r
+#define A16(x) (((U16_S *)(x))->v)\r
+\r
\r
//**************************************\r
// Macros\r
//**************************************\r
#define LZ4_HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))\r
-#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(*(U32*)(p))\r
-#define LZ4_COPYPACKET(s,d) *(U32*)d = *(U32*)s; d+=4; s+=4; *(U32*)d = *(U32*)s; d+=4; s+=4;\r
+#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p))\r
+#define LZ4_COPYPACKET(s,d) A32(d) = A32(s); d+=4; s+=4; A32(d) = A32(s); d+=4; s+=4;\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
ref = HashTable[h];\r
HashTable[h] = ip;\r
\r
- } while ((ref < ip - MAX_DISTANCE) || (*(U32*)ref != *(U32*)ip));\r
+ } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));\r
\r
// Catch up\r
while ((ip>anchor) && (ref>(BYTE*)source) && (ip[-1]==ref[-1])) { ip--; ref--; } \r
\r
_next_match:\r
// Encode Offset\r
- *(U16*)op = (ip-ref); op+=2;\r
+ A16(op) = (ip-ref); op+=2;\r
\r
// Start Counting\r
ip+=MINMATCH; ref+=MINMATCH; // MinMatch verified\r
anchor = ip;\r
while (ip<matchlimit-3)\r
{\r
- if (*(U32*)ref == *(U32*)ip) { ip+=4; ref+=4; continue; }\r
- if (*(U16*)ref == *(U16*)ip) { ip+=2; ref+=2; }\r
+ if (A32(ref) == A32(ip)) { ip+=4; ref+=4; continue; }\r
+ if (A16(ref) == A16(ip)) { ip+=2; ref+=2; }\r
if (*ref == *ip) ip++;\r
goto _endCount;\r
}\r
- if ((ip<(matchlimit-1)) && (*(U16*)ref == *(U16*)ip)) { ip+=2; ref+=2; }\r
+ if ((ip<(matchlimit-1)) && (A16(ref) == A16(ip))) { ip+=2; ref+=2; }\r
if ((ip<matchlimit) && (*ref == *ip)) ip++;\r
_endCount:\r
len = (ip - anchor);\r
// Test next position\r
ref = HashTable[LZ4_HASH_VALUE(ip)];\r
HashTable[LZ4_HASH_VALUE(ip)] = ip;\r
- if ((ref > ip - (MAX_DISTANCE + 1)) && (*(U32*)ref == *(U32*)ip)) { token = op++; *token=0; goto _next_match; }\r
+ if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { token = op++; *token=0; goto _next_match; }\r
\r
// Prepare next loop\r
anchor = ip++; \r
\r
\r
// get offset\r
- ref -= *(U16*)ip; ip+=2;\r
+ ref -= A16(ip); ip+=2;\r
\r
// get matchlength\r
if ((length=(token&ML_MASK)) == ML_MASK) { for (;*ip==255;length+=255) {ip++;} length += *ip++; } \r
*op++ = *ref++;\r
*op++ = *ref++;\r
ref -= dec[op-ref];\r
- *(U32*)op=*(U32*)ref; \r
- } else { *(U32*)op=*(U32*)ref; op+=4; ref+=4; }\r
+ A32(op)=A32(ref); \r
+ } else { A32(op)=A32(ref); op+=4; ref+=4; }\r
cpy = op + length;\r
if (cpy > oend-COPYLENGTH)\r
{\r
\r
\r
// get offset\r
- ref -= *(U16*)ip; ip+=2;\r
+ ref -= A16(ip); ip+=2;\r
\r
// get matchlength\r
if ((length=(token&ML_MASK)) == ML_MASK) { for (;(len=*ip++)==255;length+=255){} length += len; }\r
*op++ = *ref++;\r
*op++ = *ref++;\r
ref -= dec[op-ref];\r
- *(U32*)op=*(U32*)ref; \r
- } else { *(U32*)op=*(U32*)ref; op+=4; ref+=4; }\r
+ A32(op)=A32(ref); \r
+ } else { A32(op)=A32(ref); op+=4; ref+=4; }\r
cpy = op + length;\r
if (cpy>oend-COPYLENGTH)\r
{\r
#include <stdio.h> // fprintf, fopen, fread\r
#include <stdlib.h> // malloc\r
#include <string.h> // strcmp\r
+#include <time.h> // clock\r
#ifdef _WIN32 \r
#include <io.h> // _setmode\r
#include <fcntl.h> // _O_BINARY\r
//**************************************\r
// Basic Types\r
//**************************************\r
-#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__)\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
-#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
-#endif\r
+\r
\r
\r
//****************************\r
#define COMPRESSOR_VERSION ""\r
#define COMPILED __DATE__\r
#define AUTHOR "Yann Collet"\r
-#define BINARY_NAME "LZ4.exe"\r
+#define BINARY_NAME "lz4demo.exe"\r
#define EXTENSION ".lz4"\r
#define WELCOME_MESSAGE "*** %s %s, by %s (%s) ***\n", COMPRESSOR_NAME, COMPRESSOR_VERSION, AUTHOR, COMPILED\r
\r
#define ARCHIVE_MAGICNUMBER_SIZE 4\r
\r
\r
+//**************************************\r
+// MACRO\r
+//**************************************\r
+#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\r
+\r
+\r
\r
//****************************\r
// Functions\r
//****************************\r
int usage()\r
{\r
- fprintf(stderr, "Usage :\n");\r
- fprintf(stderr, " %s [arg] input output\n",BINARY_NAME);\r
- fprintf(stderr, "Arguments :\n");\r
- fprintf(stderr, " -c : compression (default)\n");\r
- fprintf(stderr, " -d : decompression \n");\r
- fprintf(stderr, " -t : test compressed file \n");\r
- fprintf(stderr, " -h : help (this text)\n"); \r
- fprintf(stderr, "input : can be 'stdin' (pipe) or a filename\n");\r
- fprintf(stderr, "output : can be 'stdout'(pipe) or a filename or 'null'\n");\r
+ DISPLAY( "Usage :\n");\r
+ DISPLAY( " %s [arg] input output\n",BINARY_NAME);\r
+ DISPLAY( "Arguments :\n");\r
+ DISPLAY( " -c : compression (default)\n");\r
+ DISPLAY( " -d : decompression \n");\r
+ DISPLAY( " -t : test compressed file \n");\r
+ DISPLAY( " -h : help (this text)\n"); \r
+ DISPLAY( "input : can be 'stdin' (pipe) or a filename\n");\r
+ DISPLAY( "output : can be 'stdout'(pipe) or a filename or 'null'\n");\r
return 0;\r
}\r
\r
\r
int badusage()\r
{\r
- fprintf(stderr, "Wrong parameters\n");\r
+ DISPLAY("Wrong parameters\n");\r
usage();\r
return 0;\r
}\r
\r
\r
-int compress_file(char* input_filename, char* output_filename)\r
+\r
+int get_fileHandle(char* input_filename, char* output_filename, FILE** pfinput, FILE** pfoutput)\r
{\r
- U64 filesize = 0;\r
- U64 compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;\r
- char* in_buff;\r
- char* out_buff;\r
- FILE* finput;\r
- FILE* foutput;\r
char stdinmark[] = "stdin";\r
char stdoutmark[] = "stdout";\r
\r
if (!strcmp (input_filename, stdinmark)) {\r
- fprintf(stderr, "Using stdin for input\n");\r
- finput = stdin;\r
+ DISPLAY( "Using stdin for input\n");\r
+ *pfinput = stdin;\r
#ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows\r
_setmode( _fileno( stdin ), _O_BINARY );\r
#endif\r
} else {\r
- finput = fopen( input_filename, "rb" );\r
+ *pfinput = fopen( input_filename, "rb" );\r
}\r
\r
if (!strcmp (output_filename, stdoutmark)) {\r
- fprintf(stderr, "Using stdout for output\n");\r
- foutput = stdout;\r
+ DISPLAY( "Using stdout for output\n");\r
+ *pfoutput = stdout;\r
#ifdef _WIN32 // Need to set stdin/stdout to binary mode specifically for windows\r
_setmode( _fileno( stdout ), _O_BINARY );\r
#endif\r
} else {\r
- foutput = fopen( output_filename, "wb" );\r
+ *pfoutput = fopen( output_filename, "wb" );\r
}\r
\r
- if ( finput==0 ) { fprintf(stderr, "Pb opening %s\n", input_filename); return 2; }\r
- if ( foutput==0) { fprintf(stderr, "Pb opening %s\n", output_filename); return 3; }\r
+ if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename); return 2; }\r
+ if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 3; }\r
+\r
+ return 0;\r
+}\r
+\r
\r
+\r
+int compress_file(char* input_filename, char* output_filename)\r
+{\r
+ unsigned long long filesize = 0;\r
+ unsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;\r
+ char* in_buff;\r
+ char* out_buff;\r
+ FILE* finput;\r
+ FILE* foutput;\r
+ int r;\r
+ clock_t start, end;\r
+\r
+\r
+ // Init\r
+ start = clock();\r
+ r = get_fileHandle(input_filename, output_filename, &finput, &foutput);\r
+ if (r) return r;\r
+ \r
// Allocate Memory\r
- in_buff = malloc(CHUNKSIZE);\r
- out_buff = malloc(OUT_CHUNKSIZE);\r
+ in_buff = (char*)malloc(CHUNKSIZE);\r
+ out_buff = (char*)malloc(OUT_CHUNKSIZE);\r
+ if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 8; }\r
\r
// Write Archive Header\r
- *(U32*)out_buff = ARCHIVE_MAGICNUMBER;\r
+ *(unsigned long*)out_buff = ARCHIVE_MAGICNUMBER;\r
fwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);\r
\r
// Main Loop\r
\r
// Compress Block\r
outSize = LZ4_compress(in_buff, out_buff+4, inSize);\r
- * (U32*) out_buff = outSize;\r
+ * (unsigned long*) out_buff = outSize;\r
compressedfilesize += outSize+4;\r
\r
// Write Block\r
}\r
\r
// Status\r
- fprintf(stderr, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n", \r
+ end = clock();\r
+ DISPLAY( "Compressed %llu bytes into %llu bytes ==> %.2f%%\n", \r
(unsigned long long) filesize, (unsigned long long) compressedfilesize, (double)compressedfilesize/filesize*100);\r
+ {\r
+ double seconds = (double)(end - start)/CLOCKS_PER_SEC;\r
+ DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);\r
+ }\r
\r
+ // Close & Free\r
+ free(in_buff);\r
+ free(out_buff);\r
fclose(finput);\r
fclose(foutput);\r
\r
\r
int decode_file(char* input_filename, char* output_filename)\r
{\r
- U64 filesize = 0;\r
+ unsigned long long filesize = 0;\r
char* in_buff;\r
char* out_buff;\r
size_t uselessRet;\r
int sinkint;\r
- U32 nextSize;\r
+ unsigned long nextSize;\r
FILE* finput;\r
FILE* foutput;\r
- char stdinmark[] = "stdin";\r
- char stdoutmark[] = "stdout";\r
+ clock_t start, end;\r
+ int r;\r
\r
- if (!strcmp (input_filename, stdinmark)) {\r
- fprintf(stderr, "Using stdin for input\n");\r
- finput = stdin;\r
-#ifdef _WIN32 // need to set stdin/stdout to binary mode\r
- _setmode( _fileno( stdin ), _O_BINARY );\r
-#endif\r
- } else {\r
- finput = fopen( input_filename, "rb" );\r
- }\r
\r
- if (!strcmp (output_filename, stdoutmark)) {\r
- fprintf(stderr, "Using stdout for output\n");\r
- foutput = stdout;\r
-#ifdef _WIN32 // need to set stdin/stdout to binary mode\r
- _setmode( _fileno( stdout ), _O_BINARY );\r
-#endif\r
- } else {\r
- foutput = fopen( output_filename, "wb" );\r
- }\r
+ // Init\r
+ start = clock();\r
+ r = get_fileHandle(input_filename, output_filename, &finput, &foutput);\r
+ if (r) return r;\r
\r
// Allocate Memory\r
- in_buff = malloc(OUT_CHUNKSIZE);\r
- out_buff = malloc(CHUNKSIZE);\r
+ in_buff = (char*)malloc(OUT_CHUNKSIZE);\r
+ out_buff = (char*)malloc(CHUNKSIZE);\r
+ if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 7; }\r
\r
// Check Archive Header\r
uselessRet = fread(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);\r
- if (*(U32*)out_buff != ARCHIVE_MAGICNUMBER) { fprintf(stderr,"Unrecognized header : file cannot be decoded\n"); return 6; }\r
+ if (*(unsigned long*)out_buff != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 6; }\r
uselessRet = fread(in_buff, 1, 4, finput);\r
- nextSize = *(U32*)in_buff;\r
+ nextSize = *(unsigned long*)in_buff;\r
\r
// Main Loop\r
while (1) \r
uselessRet = fread(in_buff, 1, nextSize, finput);\r
\r
// Check Next Block\r
- uselessRet = (U32) fread(&nextSize, 1, 4, finput);\r
+ uselessRet = (unsigned long) fread(&nextSize, 1, 4, finput);\r
if( uselessRet==0 ) break;\r
\r
// Decode Block\r
fwrite(out_buff, 1, sinkint, foutput);\r
\r
// Status\r
- fprintf(stderr, "Successfully decoded %llu bytes \n", (unsigned long long)filesize);\r
+ end = clock();\r
+ DISPLAY( "Successfully decoded %llu bytes \n", (unsigned long long)filesize);\r
+ {\r
+ double seconds = (double)(end - start)/CLOCKS_PER_SEC;\r
+ DISPLAY( "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);\r
+ }\r
\r
+ // Close & Free\r
+ free(in_buff);\r
+ free(out_buff);\r
fclose(finput);\r
fclose(foutput);\r
\r
char nullinput[] = "null";\r
\r
// Welcome message\r
- fprintf(stderr, WELCOME_MESSAGE);\r
+ DISPLAY( WELCOME_MESSAGE);\r
\r
if (argc<2) { badusage(); return 1; }\r
\r