New : ARM Validated code, thanks to Vlad Grachov.
authoryann.collet.73@gmail.com <yann.collet.73@gmail.com@650e7d94-2a16-8b24-b05c-7c0b3f6821cd>
Tue, 27 Sep 2011 11:59:58 +0000 (11:59 +0000)
committeryann.collet.73@gmail.com <yann.collet.73@gmail.com@650e7d94-2a16-8b24-b05c-7c0b3f6821cd>
Tue, 27 Sep 2011 11:59:58 +0000 (11:59 +0000)
LZ4Demo : compress/decompress output time

git-svn-id: https://lz4.googlecode.com/svn/trunk@33 650e7d94-2a16-8b24-b05c-7c0b3f6821cd

lz4.c
lz4demo.c

diff --git a/lz4.c b/lz4.c
index c8e4072..c72609d 100644 (file)
--- a/lz4.c
+++ b/lz4.c
@@ -95,13 +95,32 @@ struct refTables
        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
@@ -176,7 +195,7 @@ int LZ4_compressCtx(void** ctx,
                        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
@@ -193,19 +212,19 @@ int LZ4_compressCtx(void** ctx,
 \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
@@ -220,7 +239,7 @@ _endCount:
                // 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
@@ -308,7 +327,7 @@ int LZ4_uncompress(char* source,
 \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
@@ -321,8 +340,8 @@ int LZ4_uncompress(char* source,
                        *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
@@ -388,7 +407,7 @@ int LZ4_uncompress_unknownOutputSize(
 \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
@@ -401,8 +420,8 @@ int LZ4_uncompress_unknownOutputSize(
                        *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
index 2652e4e..ed0782d 100644 (file)
--- a/lz4demo.c
+++ b/lz4demo.c
@@ -33,6 +33,7 @@
 #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
@@ -66,7 +54,7 @@
 #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
@@ -157,7 +169,7 @@ int compress_file(char* input_filename, char* output_filename)
 \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
@@ -165,9 +177,17 @@ int compress_file(char* input_filename, char* output_filename)
        }\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
@@ -177,46 +197,33 @@ int compress_file(char* input_filename, char* output_filename)
 \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
@@ -225,7 +232,7 @@ int decode_file(char* input_filename, char* output_filename)
            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
@@ -243,8 +250,16 @@ int decode_file(char* input_filename, char* output_filename)
        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
@@ -267,7 +282,7 @@ int main(int argc, char** argv)
   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