15280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet// LZ4 streaming API example : double buffer 25280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet// Copyright : Takayuki Matsuoka 35280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 45280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 55280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#define _CRT_SECURE_NO_WARNINGS // for MSVC 65280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#include "lz4.h" 75280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 85280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#include <stdio.h> 95280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#include <stdint.h> 105280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#include <stdlib.h> 115280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet#include <string.h> 125280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 135280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletenum { 145280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet BLOCK_BYTES = 1024 * 8, 155280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet// BLOCK_BYTES = 1024 * 64, 165280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet}; 175280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 185280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 195280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletsize_t write_int(FILE* fp, int i) { 205280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return fwrite(&i, sizeof(i), 1, fp); 215280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 225280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 235280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletsize_t write_bin(FILE* fp, const void* array, size_t arrayBytes) { 245280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return fwrite(array, 1, arrayBytes, fp); 255280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 265280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 275280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletsize_t read_int(FILE* fp, int* i) { 285280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return fread(i, sizeof(*i), 1, fp); 295280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 305280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 315280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletsize_t read_bin(FILE* fp, void* array, size_t arrayBytes) { 325280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return fread(array, 1, arrayBytes, fp); 335280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 345280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 355280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 365280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletvoid test_compress(FILE* outFp, FILE* inpFp) 375280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet{ 385280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet LZ4_stream_t lz4Stream_body = { 0 }; 395280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet LZ4_stream_t* lz4Stream = &lz4Stream_body; 405280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 415280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char inpBuf[2][BLOCK_BYTES]; 425280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet int inpBufIndex = 0; 435280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 445280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet for(;;) { 455280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char* const inpPtr = inpBuf[inpBufIndex]; 465280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const int inpBytes = (int) read_bin(inpFp, inpPtr, BLOCK_BYTES); 475280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(0 == inpBytes) { 485280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 495280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 505280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 515280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 525280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; 535280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const int cmpBytes = LZ4_compress_continue( 545280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet lz4Stream, inpPtr, cmpBuf, inpBytes); 555280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(cmpBytes <= 0) { 565280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 575280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 585280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet write_int(outFp, cmpBytes); 595280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet write_bin(outFp, cmpBuf, (size_t) cmpBytes); 605280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 615280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 625280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet inpBufIndex = (inpBufIndex + 1) % 2; 635280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 645280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 655280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet write_int(outFp, 0); 665280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 675280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 685280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 695280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletvoid test_decompress(FILE* outFp, FILE* inpFp) 705280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet{ 715280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet LZ4_streamDecode_t lz4StreamDecode_body = { 0 }; 725280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; 735280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 745280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char decBuf[2][BLOCK_BYTES]; 755280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet int decBufIndex = 0; 765280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 775280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet for(;;) { 785280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; 795280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet int cmpBytes = 0; 805280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 815280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 825280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const size_t readCount0 = read_int(inpFp, &cmpBytes); 835280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(readCount0 != 1 || cmpBytes <= 0) { 845280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 855280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 865280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 875280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const size_t readCount1 = read_bin(inpFp, cmpBuf, (size_t) cmpBytes); 885280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(readCount1 != (size_t) cmpBytes) { 895280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 905280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 915280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 925280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 935280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 945280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char* const decPtr = decBuf[decBufIndex]; 955280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const int decBytes = LZ4_decompress_safe_continue( 965280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES); 975280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(decBytes <= 0) { 985280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 995280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1005280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet write_bin(outFp, decPtr, (size_t) decBytes); 1015280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1025280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1035280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet decBufIndex = (decBufIndex + 1) % 2; 1045280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1055280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 1065280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1075280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1085280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletint compare(FILE* fp0, FILE* fp1) 1095280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet{ 1105280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet int result = 0; 1115280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1125280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet while(0 == result) { 1135280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char b0[65536]; 1145280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char b1[65536]; 1155280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const size_t r0 = read_bin(fp0, b0, sizeof(b0)); 1165280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const size_t r1 = read_bin(fp1, b1, sizeof(b1)); 1175280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1185280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet result = (int) r0 - (int) r1; 1195280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1205280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(0 == r0 || 0 == r1) { 1215280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet break; 1225280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1235280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(0 == result) { 1245280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet result = memcmp(b0, b1, r0); 1255280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1265280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1275280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1285280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return result; 1295280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 1305280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1315280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1325280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Colletint main(int argc, char* argv[]) 1335280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet{ 1345280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char inpFilename[256] = { 0 }; 1355280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char lz4Filename[256] = { 0 }; 1365280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet char decFilename[256] = { 0 }; 1375280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1385280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(argc < 2) { 1395280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("Please specify input filename\n"); 1405280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return 0; 1415280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1425280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 143dc5fb73b9ee5c290cd1ea448791eefc8215b30d8Yann Collet snprintf(inpFilename, 256, "%s", argv[1]); 144dc5fb73b9ee5c290cd1ea448791eefc8215b30d8Yann Collet snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], BLOCK_BYTES); 145dc5fb73b9ee5c290cd1ea448791eefc8215b30d8Yann Collet snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], BLOCK_BYTES); 1465280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1475280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("inp = [%s]\n", inpFilename); 1485280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("lz4 = [%s]\n", lz4Filename); 1495280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("dec = [%s]\n", decFilename); 1505280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1515280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet // compress 1525280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 1535280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* inpFp = fopen(inpFilename, "rb"); 1545280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* outFp = fopen(lz4Filename, "wb"); 1555280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1565280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("compress : %s -> %s\n", inpFilename, lz4Filename); 1575280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet test_compress(outFp, inpFp); 1585280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("compress : done\n"); 1595280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1605280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(outFp); 1615280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(inpFp); 1625280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1635280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1645280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet // decompress 1655280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 1665280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* inpFp = fopen(lz4Filename, "rb"); 1675280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* outFp = fopen(decFilename, "wb"); 1685280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1695280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("decompress : %s -> %s\n", lz4Filename, decFilename); 1705280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet test_decompress(outFp, inpFp); 1715280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("decompress : done\n"); 1725280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1735280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(outFp); 1745280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(inpFp); 1755280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1765280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1775280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet // verify 1785280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet { 1795280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* inpFp = fopen(inpFilename, "rb"); 1805280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet FILE* decFp = fopen(decFilename, "rb"); 1815280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1825280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("verify : %s <-> %s\n", inpFilename, decFilename); 1835280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet const int cmp = compare(inpFp, decFp); 1845280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet if(0 == cmp) { 1855280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("verify : OK\n"); 1865280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } else { 1875280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet printf("verify : NG\n"); 1885280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1895280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1905280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(decFp); 1915280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet fclose(inpFp); 1925280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet } 1935280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet 1945280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet return 0; 1955280091f429368a9d3fa846ab47b1ada8ddf5f84Yann Collet} 196