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 13enum { 14 BLOCK_BYTES = 1024 * 8, 15// BLOCK_BYTES = 1024 * 64, 16}; 17 18 19size_t write_int(FILE* fp, int i) { 20 return fwrite(&i, sizeof(i), 1, fp); 21} 22 23size_t write_bin(FILE* fp, const void* array, size_t arrayBytes) { 24 return fwrite(array, 1, arrayBytes, fp); 25} 26 27size_t read_int(FILE* fp, int* i) { 28 return fread(i, sizeof(*i), 1, fp); 29} 30 31size_t read_bin(FILE* fp, void* array, size_t arrayBytes) { 32 return fread(array, 1, arrayBytes, fp); 33} 34 35 36void 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 69void 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 108int 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 132int 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