New : ARM Validated code, thanks to Vlad Grachov.
LZ4Demo : compress/decompress output time git-svn-id: https://lz4.googlecode.com/svn/trunk@33 650e7d94-2a16-8b24-b05c-7c0b3f6821cd
This commit is contained in:
parent
7a40bd983f
commit
ea53527d10
47
lz4.c
47
lz4.c
@ -95,13 +95,32 @@ struct refTables
|
||||
const BYTE* hashTable[HASHTABLESIZE];
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define _PACKED __attribute__ ((packed))
|
||||
#else
|
||||
# define _PACKED
|
||||
#endif
|
||||
|
||||
typedef struct _U32_S
|
||||
{
|
||||
U32 v;
|
||||
} _PACKED U32_S;
|
||||
|
||||
typedef struct _U16_S
|
||||
{
|
||||
U16 v;
|
||||
} _PACKED U16_S;
|
||||
|
||||
#define A32(x) (((U32_S *)(x))->v)
|
||||
#define A16(x) (((U16_S *)(x))->v)
|
||||
|
||||
|
||||
//**************************************
|
||||
// Macros
|
||||
//**************************************
|
||||
#define LZ4_HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
|
||||
#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(*(U32*)(p))
|
||||
#define LZ4_COPYPACKET(s,d) *(U32*)d = *(U32*)s; d+=4; s+=4; *(U32*)d = *(U32*)s; d+=4; s+=4;
|
||||
#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p))
|
||||
#define LZ4_COPYPACKET(s,d) A32(d) = A32(s); d+=4; s+=4; A32(d) = A32(s); d+=4; s+=4;
|
||||
#define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d<e);
|
||||
#define LZ4_BLINDCOPY(s,d,l) { BYTE* e=d+l; LZ4_WILDCOPY(s,d,e); d=e; }
|
||||
|
||||
@ -176,7 +195,7 @@ int LZ4_compressCtx(void** ctx,
|
||||
ref = HashTable[h];
|
||||
HashTable[h] = ip;
|
||||
|
||||
} while ((ref < ip - MAX_DISTANCE) || (*(U32*)ref != *(U32*)ip));
|
||||
} while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));
|
||||
|
||||
// Catch up
|
||||
while ((ip>anchor) && (ref>(BYTE*)source) && (ip[-1]==ref[-1])) { ip--; ref--; }
|
||||
@ -193,19 +212,19 @@ int LZ4_compressCtx(void** ctx,
|
||||
|
||||
_next_match:
|
||||
// Encode Offset
|
||||
*(U16*)op = (ip-ref); op+=2;
|
||||
A16(op) = (ip-ref); op+=2;
|
||||
|
||||
// Start Counting
|
||||
ip+=MINMATCH; ref+=MINMATCH; // MinMatch verified
|
||||
anchor = ip;
|
||||
while (ip<matchlimit-3)
|
||||
{
|
||||
if (*(U32*)ref == *(U32*)ip) { ip+=4; ref+=4; continue; }
|
||||
if (*(U16*)ref == *(U16*)ip) { ip+=2; ref+=2; }
|
||||
if (A32(ref) == A32(ip)) { ip+=4; ref+=4; continue; }
|
||||
if (A16(ref) == A16(ip)) { ip+=2; ref+=2; }
|
||||
if (*ref == *ip) ip++;
|
||||
goto _endCount;
|
||||
}
|
||||
if ((ip<(matchlimit-1)) && (*(U16*)ref == *(U16*)ip)) { ip+=2; ref+=2; }
|
||||
if ((ip<(matchlimit-1)) && (A16(ref) == A16(ip))) { ip+=2; ref+=2; }
|
||||
if ((ip<matchlimit) && (*ref == *ip)) ip++;
|
||||
_endCount:
|
||||
len = (ip - anchor);
|
||||
@ -220,7 +239,7 @@ _endCount:
|
||||
// Test next position
|
||||
ref = HashTable[LZ4_HASH_VALUE(ip)];
|
||||
HashTable[LZ4_HASH_VALUE(ip)] = ip;
|
||||
if ((ref > ip - (MAX_DISTANCE + 1)) && (*(U32*)ref == *(U32*)ip)) { token = op++; *token=0; goto _next_match; }
|
||||
if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { token = op++; *token=0; goto _next_match; }
|
||||
|
||||
// Prepare next loop
|
||||
anchor = ip++;
|
||||
@ -308,7 +327,7 @@ int LZ4_uncompress(char* source,
|
||||
|
||||
|
||||
// get offset
|
||||
ref -= *(U16*)ip; ip+=2;
|
||||
ref -= A16(ip); ip+=2;
|
||||
|
||||
// get matchlength
|
||||
if ((length=(token&ML_MASK)) == ML_MASK) { for (;*ip==255;length+=255) {ip++;} length += *ip++; }
|
||||
@ -321,8 +340,8 @@ int LZ4_uncompress(char* source,
|
||||
*op++ = *ref++;
|
||||
*op++ = *ref++;
|
||||
ref -= dec[op-ref];
|
||||
*(U32*)op=*(U32*)ref;
|
||||
} else { *(U32*)op=*(U32*)ref; op+=4; ref+=4; }
|
||||
A32(op)=A32(ref);
|
||||
} else { A32(op)=A32(ref); op+=4; ref+=4; }
|
||||
cpy = op + length;
|
||||
if (cpy > oend-COPYLENGTH)
|
||||
{
|
||||
@ -388,7 +407,7 @@ int LZ4_uncompress_unknownOutputSize(
|
||||
|
||||
|
||||
// get offset
|
||||
ref -= *(U16*)ip; ip+=2;
|
||||
ref -= A16(ip); ip+=2;
|
||||
|
||||
// get matchlength
|
||||
if ((length=(token&ML_MASK)) == ML_MASK) { for (;(len=*ip++)==255;length+=255){} length += len; }
|
||||
@ -401,8 +420,8 @@ int LZ4_uncompress_unknownOutputSize(
|
||||
*op++ = *ref++;
|
||||
*op++ = *ref++;
|
||||
ref -= dec[op-ref];
|
||||
*(U32*)op=*(U32*)ref;
|
||||
} else { *(U32*)op=*(U32*)ref; op+=4; ref+=4; }
|
||||
A32(op)=A32(ref);
|
||||
} else { A32(op)=A32(ref); op+=4; ref+=4; }
|
||||
cpy = op + length;
|
||||
if (cpy>oend-COPYLENGTH)
|
||||
{
|
||||
|
163
lz4demo.c
163
lz4demo.c
@ -33,6 +33,7 @@
|
||||
#include <stdio.h> // fprintf, fopen, fread
|
||||
#include <stdlib.h> // malloc
|
||||
#include <string.h> // strcmp
|
||||
#include <time.h> // clock
|
||||
#ifdef _WIN32
|
||||
#include <io.h> // _setmode
|
||||
#include <fcntl.h> // _O_BINARY
|
||||
@ -43,20 +44,7 @@
|
||||
//**************************************
|
||||
// Basic Types
|
||||
//**************************************
|
||||
#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__)
|
||||
#define BYTE unsigned __int8
|
||||
#define U16 unsigned __int16
|
||||
#define U32 unsigned __int32
|
||||
#define S32 __int32
|
||||
#define U64 unsigned __int64
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#define BYTE uint8_t
|
||||
#define U16 uint16_t
|
||||
#define U32 uint32_t
|
||||
#define S32 int32_t
|
||||
#define U64 uint64_t
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
@ -66,7 +54,7 @@
|
||||
#define COMPRESSOR_VERSION ""
|
||||
#define COMPILED __DATE__
|
||||
#define AUTHOR "Yann Collet"
|
||||
#define BINARY_NAME "LZ4.exe"
|
||||
#define BINARY_NAME "lz4demo.exe"
|
||||
#define EXTENSION ".lz4"
|
||||
#define WELCOME_MESSAGE "*** %s %s, by %s (%s) ***\n", COMPRESSOR_NAME, COMPRESSOR_VERSION, AUTHOR, COMPILED
|
||||
|
||||
@ -77,73 +65,97 @@
|
||||
#define ARCHIVE_MAGICNUMBER_SIZE 4
|
||||
|
||||
|
||||
//**************************************
|
||||
// MACRO
|
||||
//**************************************
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
//****************************
|
||||
// Functions
|
||||
//****************************
|
||||
int usage()
|
||||
{
|
||||
fprintf(stderr, "Usage :\n");
|
||||
fprintf(stderr, " %s [arg] input output\n",BINARY_NAME);
|
||||
fprintf(stderr, "Arguments :\n");
|
||||
fprintf(stderr, " -c : compression (default)\n");
|
||||
fprintf(stderr, " -d : decompression \n");
|
||||
fprintf(stderr, " -t : test compressed file \n");
|
||||
fprintf(stderr, " -h : help (this text)\n");
|
||||
fprintf(stderr, "input : can be 'stdin' (pipe) or a filename\n");
|
||||
fprintf(stderr, "output : can be 'stdout'(pipe) or a filename or 'null'\n");
|
||||
DISPLAY( "Usage :\n");
|
||||
DISPLAY( " %s [arg] input output\n",BINARY_NAME);
|
||||
DISPLAY( "Arguments :\n");
|
||||
DISPLAY( " -c : compression (default)\n");
|
||||
DISPLAY( " -d : decompression \n");
|
||||
DISPLAY( " -t : test 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;
|
||||
}
|
||||
|
||||
|
||||
int badusage()
|
||||
{
|
||||
fprintf(stderr, "Wrong parameters\n");
|
||||
DISPLAY("Wrong parameters\n");
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int compress_file(char* input_filename, char* output_filename)
|
||||
|
||||
int get_fileHandle(char* input_filename, char* output_filename, FILE** pfinput, FILE** pfoutput)
|
||||
{
|
||||
U64 filesize = 0;
|
||||
U64 compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;
|
||||
char* in_buff;
|
||||
char* out_buff;
|
||||
FILE* finput;
|
||||
FILE* foutput;
|
||||
char stdinmark[] = "stdin";
|
||||
char stdoutmark[] = "stdout";
|
||||
|
||||
if (!strcmp (input_filename, stdinmark)) {
|
||||
fprintf(stderr, "Using stdin for input\n");
|
||||
finput = stdin;
|
||||
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 );
|
||||
#endif
|
||||
} else {
|
||||
finput = fopen( input_filename, "rb" );
|
||||
*pfinput = fopen( input_filename, "rb" );
|
||||
}
|
||||
|
||||
if (!strcmp (output_filename, stdoutmark)) {
|
||||
fprintf(stderr, "Using stdout for output\n");
|
||||
foutput = stdout;
|
||||
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 );
|
||||
#endif
|
||||
} else {
|
||||
foutput = fopen( output_filename, "wb" );
|
||||
*pfoutput = fopen( output_filename, "wb" );
|
||||
}
|
||||
|
||||
if ( finput==0 ) { fprintf(stderr, "Pb opening %s\n", input_filename); return 2; }
|
||||
if ( foutput==0) { fprintf(stderr, "Pb opening %s\n", output_filename); return 3; }
|
||||
if ( *pfinput==0 ) { DISPLAY( "Pb opening %s\n", input_filename); return 2; }
|
||||
if ( *pfoutput==0) { DISPLAY( "Pb opening %s\n", output_filename); return 3; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int compress_file(char* input_filename, char* output_filename)
|
||||
{
|
||||
unsigned long long filesize = 0;
|
||||
unsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;
|
||||
char* in_buff;
|
||||
char* out_buff;
|
||||
FILE* finput;
|
||||
FILE* foutput;
|
||||
int r;
|
||||
clock_t start, end;
|
||||
|
||||
|
||||
// Init
|
||||
start = clock();
|
||||
r = get_fileHandle(input_filename, output_filename, &finput, &foutput);
|
||||
if (r) return r;
|
||||
|
||||
// Allocate Memory
|
||||
in_buff = malloc(CHUNKSIZE);
|
||||
out_buff = malloc(OUT_CHUNKSIZE);
|
||||
in_buff = (char*)malloc(CHUNKSIZE);
|
||||
out_buff = (char*)malloc(OUT_CHUNKSIZE);
|
||||
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 8; }
|
||||
|
||||
// Write Archive Header
|
||||
*(U32*)out_buff = ARCHIVE_MAGICNUMBER;
|
||||
*(unsigned long*)out_buff = ARCHIVE_MAGICNUMBER;
|
||||
fwrite(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, foutput);
|
||||
|
||||
// Main Loop
|
||||
@ -157,7 +169,7 @@ int compress_file(char* input_filename, char* output_filename)
|
||||
|
||||
// Compress Block
|
||||
outSize = LZ4_compress(in_buff, out_buff+4, inSize);
|
||||
* (U32*) out_buff = outSize;
|
||||
* (unsigned long*) out_buff = outSize;
|
||||
compressedfilesize += outSize+4;
|
||||
|
||||
// Write Block
|
||||
@ -165,9 +177,17 @@ int compress_file(char* input_filename, char* output_filename)
|
||||
}
|
||||
|
||||
// Status
|
||||
fprintf(stderr, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n",
|
||||
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);
|
||||
|
||||
@ -177,46 +197,33 @@ int compress_file(char* input_filename, char* output_filename)
|
||||
|
||||
int decode_file(char* input_filename, char* output_filename)
|
||||
{
|
||||
U64 filesize = 0;
|
||||
unsigned long long filesize = 0;
|
||||
char* in_buff;
|
||||
char* out_buff;
|
||||
size_t uselessRet;
|
||||
int sinkint;
|
||||
U32 nextSize;
|
||||
unsigned long nextSize;
|
||||
FILE* finput;
|
||||
FILE* foutput;
|
||||
char stdinmark[] = "stdin";
|
||||
char stdoutmark[] = "stdout";
|
||||
clock_t start, end;
|
||||
int r;
|
||||
|
||||
if (!strcmp (input_filename, stdinmark)) {
|
||||
fprintf(stderr, "Using stdin for input\n");
|
||||
finput = stdin;
|
||||
#ifdef _WIN32 // need to set stdin/stdout to binary mode
|
||||
_setmode( _fileno( stdin ), _O_BINARY );
|
||||
#endif
|
||||
} else {
|
||||
finput = fopen( input_filename, "rb" );
|
||||
}
|
||||
|
||||
if (!strcmp (output_filename, stdoutmark)) {
|
||||
fprintf(stderr, "Using stdout for output\n");
|
||||
foutput = stdout;
|
||||
#ifdef _WIN32 // need to set stdin/stdout to binary mode
|
||||
_setmode( _fileno( stdout ), _O_BINARY );
|
||||
#endif
|
||||
} else {
|
||||
foutput = fopen( output_filename, "wb" );
|
||||
}
|
||||
// Init
|
||||
start = clock();
|
||||
r = get_fileHandle(input_filename, output_filename, &finput, &foutput);
|
||||
if (r) return r;
|
||||
|
||||
// Allocate Memory
|
||||
in_buff = malloc(OUT_CHUNKSIZE);
|
||||
out_buff = malloc(CHUNKSIZE);
|
||||
in_buff = (char*)malloc(OUT_CHUNKSIZE);
|
||||
out_buff = (char*)malloc(CHUNKSIZE);
|
||||
if (!in_buff || !out_buff) { DISPLAY("Allocation error : not enough memory\n"); return 7; }
|
||||
|
||||
// Check Archive Header
|
||||
uselessRet = fread(out_buff, 1, ARCHIVE_MAGICNUMBER_SIZE, finput);
|
||||
if (*(U32*)out_buff != ARCHIVE_MAGICNUMBER) { fprintf(stderr,"Unrecognized header : file cannot be decoded\n"); return 6; }
|
||||
if (*(unsigned long*)out_buff != ARCHIVE_MAGICNUMBER) { DISPLAY("Unrecognized header : file cannot be decoded\n"); return 6; }
|
||||
uselessRet = fread(in_buff, 1, 4, finput);
|
||||
nextSize = *(U32*)in_buff;
|
||||
nextSize = *(unsigned long*)in_buff;
|
||||
|
||||
// Main Loop
|
||||
while (1)
|
||||
@ -225,7 +232,7 @@ int decode_file(char* input_filename, char* output_filename)
|
||||
uselessRet = fread(in_buff, 1, nextSize, finput);
|
||||
|
||||
// Check Next Block
|
||||
uselessRet = (U32) fread(&nextSize, 1, 4, finput);
|
||||
uselessRet = (unsigned long) fread(&nextSize, 1, 4, finput);
|
||||
if( uselessRet==0 ) break;
|
||||
|
||||
// Decode Block
|
||||
@ -243,8 +250,16 @@ int decode_file(char* input_filename, char* output_filename)
|
||||
fwrite(out_buff, 1, sinkint, foutput);
|
||||
|
||||
// Status
|
||||
fprintf(stderr, "Successfully decoded %llu bytes \n", (unsigned long long)filesize);
|
||||
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);
|
||||
}
|
||||
|
||||
// Close & Free
|
||||
free(in_buff);
|
||||
free(out_buff);
|
||||
fclose(finput);
|
||||
fclose(foutput);
|
||||
|
||||
@ -267,7 +282,7 @@ int main(int argc, char** argv)
|
||||
char nullinput[] = "null";
|
||||
|
||||
// Welcome message
|
||||
fprintf(stderr, WELCOME_MESSAGE);
|
||||
DISPLAY( WELCOME_MESSAGE);
|
||||
|
||||
if (argc<2) { badusage(); return 1; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user