1*27162e4eSAndroid Build Coastguard Worker /* LZ4 streaming API example : ring buffer
2*27162e4eSAndroid Build Coastguard Worker * Based on sample code from Takayuki Matsuoka */
3*27162e4eSAndroid Build Coastguard Worker
4*27162e4eSAndroid Build Coastguard Worker
5*27162e4eSAndroid Build Coastguard Worker /**************************************
6*27162e4eSAndroid Build Coastguard Worker * Compiler Options
7*27162e4eSAndroid Build Coastguard Worker **************************************/
8*27162e4eSAndroid Build Coastguard Worker #if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */
9*27162e4eSAndroid Build Coastguard Worker # define _CRT_SECURE_NO_WARNINGS
10*27162e4eSAndroid Build Coastguard Worker # define snprintf sprintf_s
11*27162e4eSAndroid Build Coastguard Worker #endif
12*27162e4eSAndroid Build Coastguard Worker
13*27162e4eSAndroid Build Coastguard Worker
14*27162e4eSAndroid Build Coastguard Worker /**************************************
15*27162e4eSAndroid Build Coastguard Worker * Includes
16*27162e4eSAndroid Build Coastguard Worker **************************************/
17*27162e4eSAndroid Build Coastguard Worker #include <stdio.h>
18*27162e4eSAndroid Build Coastguard Worker #include <stdint.h>
19*27162e4eSAndroid Build Coastguard Worker #include <stdlib.h>
20*27162e4eSAndroid Build Coastguard Worker #include <string.h>
21*27162e4eSAndroid Build Coastguard Worker #include "lz4.h"
22*27162e4eSAndroid Build Coastguard Worker
23*27162e4eSAndroid Build Coastguard Worker
24*27162e4eSAndroid Build Coastguard Worker enum {
25*27162e4eSAndroid Build Coastguard Worker MESSAGE_MAX_BYTES = 1024,
26*27162e4eSAndroid Build Coastguard Worker RING_BUFFER_BYTES = 1024 * 8 + MESSAGE_MAX_BYTES,
27*27162e4eSAndroid Build Coastguard Worker DECODE_RING_BUFFER = RING_BUFFER_BYTES + MESSAGE_MAX_BYTES /* Intentionally larger, to test unsynchronized ring buffers */
28*27162e4eSAndroid Build Coastguard Worker };
29*27162e4eSAndroid Build Coastguard Worker
30*27162e4eSAndroid Build Coastguard Worker
write_int32(FILE * fp,int32_t i)31*27162e4eSAndroid Build Coastguard Worker size_t write_int32(FILE* fp, int32_t i) {
32*27162e4eSAndroid Build Coastguard Worker return fwrite(&i, sizeof(i), 1, fp);
33*27162e4eSAndroid Build Coastguard Worker }
34*27162e4eSAndroid Build Coastguard Worker
write_bin(FILE * fp,const void * array,int arrayBytes)35*27162e4eSAndroid Build Coastguard Worker size_t write_bin(FILE* fp, const void* array, int arrayBytes) {
36*27162e4eSAndroid Build Coastguard Worker return fwrite(array, 1, arrayBytes, fp);
37*27162e4eSAndroid Build Coastguard Worker }
38*27162e4eSAndroid Build Coastguard Worker
read_int32(FILE * fp,int32_t * i)39*27162e4eSAndroid Build Coastguard Worker size_t read_int32(FILE* fp, int32_t* i) {
40*27162e4eSAndroid Build Coastguard Worker return fread(i, sizeof(*i), 1, fp);
41*27162e4eSAndroid Build Coastguard Worker }
42*27162e4eSAndroid Build Coastguard Worker
read_bin(FILE * fp,void * array,int arrayBytes)43*27162e4eSAndroid Build Coastguard Worker size_t read_bin(FILE* fp, void* array, int arrayBytes) {
44*27162e4eSAndroid Build Coastguard Worker return fread(array, 1, arrayBytes, fp);
45*27162e4eSAndroid Build Coastguard Worker }
46*27162e4eSAndroid Build Coastguard Worker
47*27162e4eSAndroid Build Coastguard Worker
test_compress(FILE * outFp,FILE * inpFp)48*27162e4eSAndroid Build Coastguard Worker void test_compress(FILE* outFp, FILE* inpFp)
49*27162e4eSAndroid Build Coastguard Worker {
50*27162e4eSAndroid Build Coastguard Worker LZ4_stream_t lz4Stream_body = { { 0 } };
51*27162e4eSAndroid Build Coastguard Worker LZ4_stream_t* lz4Stream = &lz4Stream_body;
52*27162e4eSAndroid Build Coastguard Worker
53*27162e4eSAndroid Build Coastguard Worker static char inpBuf[RING_BUFFER_BYTES];
54*27162e4eSAndroid Build Coastguard Worker int inpOffset = 0;
55*27162e4eSAndroid Build Coastguard Worker
56*27162e4eSAndroid Build Coastguard Worker for(;;) {
57*27162e4eSAndroid Build Coastguard Worker // Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer.
58*27162e4eSAndroid Build Coastguard Worker char* const inpPtr = &inpBuf[inpOffset];
59*27162e4eSAndroid Build Coastguard Worker const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1;
60*27162e4eSAndroid Build Coastguard Worker const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength);
61*27162e4eSAndroid Build Coastguard Worker if (0 == inpBytes) break;
62*27162e4eSAndroid Build Coastguard Worker
63*27162e4eSAndroid Build Coastguard Worker {
64*27162e4eSAndroid Build Coastguard Worker #define CMPBUFSIZE (LZ4_COMPRESSBOUND(MESSAGE_MAX_BYTES))
65*27162e4eSAndroid Build Coastguard Worker char cmpBuf[CMPBUFSIZE];
66*27162e4eSAndroid Build Coastguard Worker const int cmpBytes = LZ4_compress_fast_continue(lz4Stream, inpPtr, cmpBuf, inpBytes, CMPBUFSIZE, 0);
67*27162e4eSAndroid Build Coastguard Worker if(cmpBytes <= 0) break;
68*27162e4eSAndroid Build Coastguard Worker write_int32(outFp, cmpBytes);
69*27162e4eSAndroid Build Coastguard Worker write_bin(outFp, cmpBuf, cmpBytes);
70*27162e4eSAndroid Build Coastguard Worker
71*27162e4eSAndroid Build Coastguard Worker inpOffset += inpBytes;
72*27162e4eSAndroid Build Coastguard Worker
73*27162e4eSAndroid Build Coastguard Worker // Wraparound the ringbuffer offset
74*27162e4eSAndroid Build Coastguard Worker if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) inpOffset = 0;
75*27162e4eSAndroid Build Coastguard Worker }
76*27162e4eSAndroid Build Coastguard Worker }
77*27162e4eSAndroid Build Coastguard Worker
78*27162e4eSAndroid Build Coastguard Worker write_int32(outFp, 0);
79*27162e4eSAndroid Build Coastguard Worker }
80*27162e4eSAndroid Build Coastguard Worker
81*27162e4eSAndroid Build Coastguard Worker
test_decompress(FILE * outFp,FILE * inpFp)82*27162e4eSAndroid Build Coastguard Worker void test_decompress(FILE* outFp, FILE* inpFp)
83*27162e4eSAndroid Build Coastguard Worker {
84*27162e4eSAndroid Build Coastguard Worker static char decBuf[DECODE_RING_BUFFER];
85*27162e4eSAndroid Build Coastguard Worker int decOffset = 0;
86*27162e4eSAndroid Build Coastguard Worker LZ4_streamDecode_t lz4StreamDecode_body = { { 0 } };
87*27162e4eSAndroid Build Coastguard Worker LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body;
88*27162e4eSAndroid Build Coastguard Worker
89*27162e4eSAndroid Build Coastguard Worker for(;;) {
90*27162e4eSAndroid Build Coastguard Worker int cmpBytes = 0;
91*27162e4eSAndroid Build Coastguard Worker char cmpBuf[CMPBUFSIZE];
92*27162e4eSAndroid Build Coastguard Worker
93*27162e4eSAndroid Build Coastguard Worker { const size_t r0 = read_int32(inpFp, &cmpBytes);
94*27162e4eSAndroid Build Coastguard Worker if(r0 != 1 || cmpBytes <= 0) break;
95*27162e4eSAndroid Build Coastguard Worker
96*27162e4eSAndroid Build Coastguard Worker const size_t r1 = read_bin(inpFp, cmpBuf, cmpBytes);
97*27162e4eSAndroid Build Coastguard Worker if(r1 != (size_t) cmpBytes) break;
98*27162e4eSAndroid Build Coastguard Worker }
99*27162e4eSAndroid Build Coastguard Worker
100*27162e4eSAndroid Build Coastguard Worker { char* const decPtr = &decBuf[decOffset];
101*27162e4eSAndroid Build Coastguard Worker const int decBytes = LZ4_decompress_safe_continue(
102*27162e4eSAndroid Build Coastguard Worker lz4StreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES);
103*27162e4eSAndroid Build Coastguard Worker if(decBytes <= 0) break;
104*27162e4eSAndroid Build Coastguard Worker decOffset += decBytes;
105*27162e4eSAndroid Build Coastguard Worker write_bin(outFp, decPtr, decBytes);
106*27162e4eSAndroid Build Coastguard Worker
107*27162e4eSAndroid Build Coastguard Worker // Wraparound the ringbuffer offset
108*27162e4eSAndroid Build Coastguard Worker if(decOffset >= DECODE_RING_BUFFER - MESSAGE_MAX_BYTES) decOffset = 0;
109*27162e4eSAndroid Build Coastguard Worker }
110*27162e4eSAndroid Build Coastguard Worker }
111*27162e4eSAndroid Build Coastguard Worker }
112*27162e4eSAndroid Build Coastguard Worker
113*27162e4eSAndroid Build Coastguard Worker
compare(FILE * f0,FILE * f1)114*27162e4eSAndroid Build Coastguard Worker int compare(FILE* f0, FILE* f1)
115*27162e4eSAndroid Build Coastguard Worker {
116*27162e4eSAndroid Build Coastguard Worker int result = 0;
117*27162e4eSAndroid Build Coastguard Worker
118*27162e4eSAndroid Build Coastguard Worker while (0 == result) {
119*27162e4eSAndroid Build Coastguard Worker char b0[65536];
120*27162e4eSAndroid Build Coastguard Worker char b1[65536];
121*27162e4eSAndroid Build Coastguard Worker const size_t r0 = fread(b0, 1, sizeof(b0), f0);
122*27162e4eSAndroid Build Coastguard Worker const size_t r1 = fread(b1, 1, sizeof(b1), f1);
123*27162e4eSAndroid Build Coastguard Worker
124*27162e4eSAndroid Build Coastguard Worker result = (int) r0 - (int) r1;
125*27162e4eSAndroid Build Coastguard Worker
126*27162e4eSAndroid Build Coastguard Worker if (0 == r0 || 0 == r1) break;
127*27162e4eSAndroid Build Coastguard Worker
128*27162e4eSAndroid Build Coastguard Worker if (0 == result) result = memcmp(b0, b1, r0);
129*27162e4eSAndroid Build Coastguard Worker }
130*27162e4eSAndroid Build Coastguard Worker
131*27162e4eSAndroid Build Coastguard Worker return result;
132*27162e4eSAndroid Build Coastguard Worker }
133*27162e4eSAndroid Build Coastguard Worker
134*27162e4eSAndroid Build Coastguard Worker
main(int argc,char ** argv)135*27162e4eSAndroid Build Coastguard Worker int main(int argc, char** argv)
136*27162e4eSAndroid Build Coastguard Worker {
137*27162e4eSAndroid Build Coastguard Worker char inpFilename[256] = { 0 };
138*27162e4eSAndroid Build Coastguard Worker char lz4Filename[256] = { 0 };
139*27162e4eSAndroid Build Coastguard Worker char decFilename[256] = { 0 };
140*27162e4eSAndroid Build Coastguard Worker
141*27162e4eSAndroid Build Coastguard Worker if (argc < 2) {
142*27162e4eSAndroid Build Coastguard Worker printf("Please specify input filename\n");
143*27162e4eSAndroid Build Coastguard Worker return 0;
144*27162e4eSAndroid Build Coastguard Worker }
145*27162e4eSAndroid Build Coastguard Worker
146*27162e4eSAndroid Build Coastguard Worker snprintf(inpFilename, 256, "%s", argv[1]);
147*27162e4eSAndroid Build Coastguard Worker snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], 0);
148*27162e4eSAndroid Build Coastguard Worker snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], 0);
149*27162e4eSAndroid Build Coastguard Worker
150*27162e4eSAndroid Build Coastguard Worker printf("inp = [%s]\n", inpFilename);
151*27162e4eSAndroid Build Coastguard Worker printf("lz4 = [%s]\n", lz4Filename);
152*27162e4eSAndroid Build Coastguard Worker printf("dec = [%s]\n", decFilename);
153*27162e4eSAndroid Build Coastguard Worker
154*27162e4eSAndroid Build Coastguard Worker // compress
155*27162e4eSAndroid Build Coastguard Worker { FILE* const inpFp = fopen(inpFilename, "rb");
156*27162e4eSAndroid Build Coastguard Worker FILE* const outFp = fopen(lz4Filename, "wb");
157*27162e4eSAndroid Build Coastguard Worker
158*27162e4eSAndroid Build Coastguard Worker test_compress(outFp, inpFp);
159*27162e4eSAndroid Build Coastguard Worker
160*27162e4eSAndroid Build Coastguard Worker fclose(outFp);
161*27162e4eSAndroid Build Coastguard Worker fclose(inpFp);
162*27162e4eSAndroid Build Coastguard Worker }
163*27162e4eSAndroid Build Coastguard Worker
164*27162e4eSAndroid Build Coastguard Worker // decompress
165*27162e4eSAndroid Build Coastguard Worker { FILE* const inpFp = fopen(lz4Filename, "rb");
166*27162e4eSAndroid Build Coastguard Worker FILE* const outFp = fopen(decFilename, "wb");
167*27162e4eSAndroid Build Coastguard Worker
168*27162e4eSAndroid Build Coastguard Worker test_decompress(outFp, inpFp);
169*27162e4eSAndroid Build Coastguard Worker
170*27162e4eSAndroid Build Coastguard Worker fclose(outFp);
171*27162e4eSAndroid Build Coastguard Worker fclose(inpFp);
172*27162e4eSAndroid Build Coastguard Worker }
173*27162e4eSAndroid Build Coastguard Worker
174*27162e4eSAndroid Build Coastguard Worker // verify
175*27162e4eSAndroid Build Coastguard Worker { FILE* const inpFp = fopen(inpFilename, "rb");
176*27162e4eSAndroid Build Coastguard Worker FILE* const decFp = fopen(decFilename, "rb");
177*27162e4eSAndroid Build Coastguard Worker
178*27162e4eSAndroid Build Coastguard Worker const int cmp = compare(inpFp, decFp);
179*27162e4eSAndroid Build Coastguard Worker if (0 == cmp) {
180*27162e4eSAndroid Build Coastguard Worker printf("Verify : OK\n");
181*27162e4eSAndroid Build Coastguard Worker } else {
182*27162e4eSAndroid Build Coastguard Worker printf("Verify : NG\n");
183*27162e4eSAndroid Build Coastguard Worker }
184*27162e4eSAndroid Build Coastguard Worker
185*27162e4eSAndroid Build Coastguard Worker fclose(decFp);
186*27162e4eSAndroid Build Coastguard Worker fclose(inpFp);
187*27162e4eSAndroid Build Coastguard Worker }
188*27162e4eSAndroid Build Coastguard Worker
189*27162e4eSAndroid Build Coastguard Worker return 0;
190*27162e4eSAndroid Build Coastguard Worker }
191