-
-
Save BH1SCW/94d4f43c62cdc4a6f57066e4e274472b to your computer and use it in GitHub Desktop.
Takayuki's Streaming example 2 (simplified)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// LZ4 streaming API example 2 (ring buffer) | |
#define _CRT_SECURE_NO_WARNINGS // for MSVC | |
#include "lz4.h" | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
enum { | |
MESSAGE_MAX_BYTES = 1024, | |
RING_BUFFER_BYTES = 1024 * 256 + MESSAGE_MAX_BYTES, | |
DICT_BYTES = 65536, | |
}; | |
size_t write_int32(FILE* fp, int32_t i) { | |
return fwrite(&i, sizeof(i), 1, fp); | |
} | |
size_t write_bin(FILE* fp, const void* array, int arrayBytes) { | |
return fwrite(array, 1, arrayBytes, fp); | |
} | |
size_t read_int32(FILE* fp, int32_t* i) { | |
return fread(i, sizeof(*i), 1, fp); | |
} | |
size_t read_bin(FILE* fp, void* array, int arrayBytes) { | |
return fread(array, 1, arrayBytes, fp); | |
} | |
void test_compress(FILE* outFp, FILE* inpFp) | |
{ | |
LZ4_stream_t lz4Stream_body = { 0 }; | |
LZ4_stream_t* lz4Stream = &lz4Stream_body; | |
static char inpBuf[RING_BUFFER_BYTES]; | |
int inpOffset = 0; | |
for(;;) { | |
// Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer. | |
char* const inpPtr = &inpBuf[inpOffset]; | |
const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1; | |
const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength); | |
if (0 == inpBytes) break; | |
{ | |
char cmpBuf[LZ4_COMPRESSBOUND(MESSAGE_MAX_BYTES)]; | |
const int cmpBytes = LZ4_compress_continue(lz4Stream, inpPtr, cmpBuf, inpBytes); | |
if(cmpBytes <= 0) break; | |
write_int32(outFp, cmpBytes); | |
write_bin(outFp, cmpBuf, cmpBytes); | |
inpOffset += inpBytes; | |
// Wraparound the ringbuffer offset | |
if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) inpOffset = 0; | |
} | |
} | |
write_int32(outFp, 0); | |
} | |
void test_decompress(FILE* outFp, FILE* inpFp) | |
{ | |
static char decBuf[RING_BUFFER_BYTES]; | |
int decOffset = 0; | |
LZ4_streamDecode_t lz4StreamDecode_body = { 0 }; | |
LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; | |
for(;;) { | |
int cmpBytes = 0; | |
char cmpBuf[LZ4_COMPRESSBOUND(MESSAGE_MAX_BYTES)]; | |
{ | |
const size_t r0 = read_int32(inpFp, &cmpBytes); | |
if(r0 != 1 || cmpBytes <= 0) break; | |
const size_t r1 = read_bin(inpFp, cmpBuf, cmpBytes); | |
if(r1 != (size_t) cmpBytes) break; | |
} | |
{ | |
char* const decPtr = &decBuf[decOffset]; | |
const int decBytes = LZ4_decompress_safe_continue( | |
lz4StreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES); | |
if(decBytes <= 0) break; | |
decOffset += decBytes; | |
write_bin(outFp, decPtr, decBytes); | |
// Wraparound the ringbuffer offset | |
if(decOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) decOffset = 0; | |
} | |
} | |
} | |
int compare(FILE* f0, FILE* f1) | |
{ | |
int result = 0; | |
while(0 == result) { | |
char b0[65536]; | |
char b1[65536]; | |
const size_t r0 = fread(b0, 1, sizeof(b0), f0); | |
const size_t r1 = fread(b1, 1, sizeof(b1), f1); | |
result = (int) r0 - (int) r1; | |
if(0 == r0 || 0 == r1) { | |
break; | |
} | |
if(0 == result) { | |
result = memcmp(b0, b1, r0); | |
} | |
} | |
return result; | |
} | |
int main(int argc, char** argv[]) | |
{ | |
char inpFilename[256] = { 0 }; | |
char lz4Filename[256] = { 0 }; | |
char decFilename[256] = { 0 }; | |
if(argc < 2) { | |
printf("Please specify input filename\n"); | |
return 0; | |
} | |
sprintf(inpFilename, "%s", argv[1]); | |
sprintf(lz4Filename, "%s.lz4s-%d", argv[1], 0); | |
sprintf(decFilename, "%s.lz4s-%d.dec", argv[1], 0); | |
printf("inp = [%s]\n", inpFilename); | |
printf("lz4 = [%s]\n", lz4Filename); | |
printf("dec = [%s]\n", decFilename); | |
// compress | |
{ | |
FILE* inpFp = fopen(inpFilename, "rb"); | |
FILE* outFp = fopen(lz4Filename, "wb"); | |
test_compress(outFp, inpFp); | |
fclose(outFp); | |
fclose(inpFp); | |
} | |
// decompress | |
{ | |
FILE* inpFp = fopen(lz4Filename, "rb"); | |
FILE* outFp = fopen(decFilename, "wb"); | |
test_decompress(outFp, inpFp); | |
fclose(outFp); | |
fclose(inpFp); | |
} | |
// verify | |
{ | |
FILE* inpFp = fopen(inpFilename, "rb"); | |
FILE* decFp = fopen(decFilename, "rb"); | |
const int cmp = compare(inpFp, decFp); | |
if(0 == cmp) { | |
printf("Verify : OK\n"); | |
} else { | |
printf("Verify : NG\n"); | |
} | |
fclose(decFp); | |
fclose(inpFp); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment