• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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