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