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