127b27ec6Sopenharmony_ci/* LZ4file API example : compress a file
227b27ec6Sopenharmony_ci * Modified from an example code by anjiahao
327b27ec6Sopenharmony_ci *
427b27ec6Sopenharmony_ci * This example will demonstrate how
527b27ec6Sopenharmony_ci * to manipulate lz4 compressed files like
627b27ec6Sopenharmony_ci * normal files */
727b27ec6Sopenharmony_ci
827b27ec6Sopenharmony_ci#include <assert.h>
927b27ec6Sopenharmony_ci#include <stdio.h>
1027b27ec6Sopenharmony_ci#include <stdlib.h>
1127b27ec6Sopenharmony_ci#include <string.h>
1227b27ec6Sopenharmony_ci#include <sys/stat.h>
1327b27ec6Sopenharmony_ci
1427b27ec6Sopenharmony_ci#include <lz4file.h>
1527b27ec6Sopenharmony_ci
1627b27ec6Sopenharmony_ci
1727b27ec6Sopenharmony_ci#define CHUNK_SIZE (16*1024)
1827b27ec6Sopenharmony_ci
1927b27ec6Sopenharmony_cistatic size_t get_file_size(char *filename)
2027b27ec6Sopenharmony_ci{
2127b27ec6Sopenharmony_ci    struct stat statbuf;
2227b27ec6Sopenharmony_ci
2327b27ec6Sopenharmony_ci    if (filename == NULL) {
2427b27ec6Sopenharmony_ci        return 0;
2527b27ec6Sopenharmony_ci    }
2627b27ec6Sopenharmony_ci
2727b27ec6Sopenharmony_ci    if(stat(filename,&statbuf)) {
2827b27ec6Sopenharmony_ci        return 0;
2927b27ec6Sopenharmony_ci    }
3027b27ec6Sopenharmony_ci
3127b27ec6Sopenharmony_ci    return statbuf.st_size;
3227b27ec6Sopenharmony_ci}
3327b27ec6Sopenharmony_ci
3427b27ec6Sopenharmony_cistatic int compress_file(FILE* f_in, FILE* f_out)
3527b27ec6Sopenharmony_ci{
3627b27ec6Sopenharmony_ci    assert(f_in != NULL); assert(f_out != NULL);
3727b27ec6Sopenharmony_ci
3827b27ec6Sopenharmony_ci    LZ4F_errorCode_t ret = LZ4F_OK_NoError;
3927b27ec6Sopenharmony_ci    size_t len;
4027b27ec6Sopenharmony_ci    LZ4_writeFile_t* lz4fWrite;
4127b27ec6Sopenharmony_ci    void* const buf = malloc(CHUNK_SIZE);
4227b27ec6Sopenharmony_ci    if (!buf) {
4327b27ec6Sopenharmony_ci        printf("error: memory allocation failed \n");
4427b27ec6Sopenharmony_ci    }
4527b27ec6Sopenharmony_ci
4627b27ec6Sopenharmony_ci    /* Of course, you can also use prefsPtr to
4727b27ec6Sopenharmony_ci     * set the parameters of the compressed file
4827b27ec6Sopenharmony_ci     * NULL is use default
4927b27ec6Sopenharmony_ci     */
5027b27ec6Sopenharmony_ci    ret = LZ4F_writeOpen(&lz4fWrite, f_out, NULL);
5127b27ec6Sopenharmony_ci    if (LZ4F_isError(ret)) {
5227b27ec6Sopenharmony_ci        printf("LZ4F_writeOpen error: %s\n", LZ4F_getErrorName(ret));
5327b27ec6Sopenharmony_ci        free(buf);
5427b27ec6Sopenharmony_ci        return 1;
5527b27ec6Sopenharmony_ci    }
5627b27ec6Sopenharmony_ci
5727b27ec6Sopenharmony_ci    while (1) {
5827b27ec6Sopenharmony_ci        len = fread(buf, 1, CHUNK_SIZE, f_in);
5927b27ec6Sopenharmony_ci
6027b27ec6Sopenharmony_ci        if (ferror(f_in)) {
6127b27ec6Sopenharmony_ci            printf("fread error\n");
6227b27ec6Sopenharmony_ci            goto out;
6327b27ec6Sopenharmony_ci        }
6427b27ec6Sopenharmony_ci
6527b27ec6Sopenharmony_ci        /* nothing to read */
6627b27ec6Sopenharmony_ci        if (len == 0) {
6727b27ec6Sopenharmony_ci            break;
6827b27ec6Sopenharmony_ci        }
6927b27ec6Sopenharmony_ci
7027b27ec6Sopenharmony_ci        ret = LZ4F_write(lz4fWrite, buf, len);
7127b27ec6Sopenharmony_ci        if (LZ4F_isError(ret)) {
7227b27ec6Sopenharmony_ci            printf("LZ4F_write: %s\n", LZ4F_getErrorName(ret));
7327b27ec6Sopenharmony_ci            goto out;
7427b27ec6Sopenharmony_ci        }
7527b27ec6Sopenharmony_ci    }
7627b27ec6Sopenharmony_ci
7727b27ec6Sopenharmony_ciout:
7827b27ec6Sopenharmony_ci    free(buf);
7927b27ec6Sopenharmony_ci    if (LZ4F_isError(LZ4F_writeClose(lz4fWrite))) {
8027b27ec6Sopenharmony_ci        printf("LZ4F_writeClose: %s\n", LZ4F_getErrorName(ret));
8127b27ec6Sopenharmony_ci        return 1;
8227b27ec6Sopenharmony_ci    }
8327b27ec6Sopenharmony_ci
8427b27ec6Sopenharmony_ci    return 0;
8527b27ec6Sopenharmony_ci}
8627b27ec6Sopenharmony_ci
8727b27ec6Sopenharmony_cistatic int decompress_file(FILE* f_in, FILE* f_out)
8827b27ec6Sopenharmony_ci{
8927b27ec6Sopenharmony_ci    assert(f_in != NULL); assert(f_out != NULL);
9027b27ec6Sopenharmony_ci
9127b27ec6Sopenharmony_ci    LZ4F_errorCode_t ret = LZ4F_OK_NoError;
9227b27ec6Sopenharmony_ci    LZ4_readFile_t* lz4fRead;
9327b27ec6Sopenharmony_ci    void* const buf= malloc(CHUNK_SIZE);
9427b27ec6Sopenharmony_ci    if (!buf) {
9527b27ec6Sopenharmony_ci        printf("error: memory allocation failed \n");
9627b27ec6Sopenharmony_ci    }
9727b27ec6Sopenharmony_ci
9827b27ec6Sopenharmony_ci    ret = LZ4F_readOpen(&lz4fRead, f_in);
9927b27ec6Sopenharmony_ci    if (LZ4F_isError(ret)) {
10027b27ec6Sopenharmony_ci        printf("LZ4F_readOpen error: %s\n", LZ4F_getErrorName(ret));
10127b27ec6Sopenharmony_ci        free(buf);
10227b27ec6Sopenharmony_ci        return 1;
10327b27ec6Sopenharmony_ci    }
10427b27ec6Sopenharmony_ci
10527b27ec6Sopenharmony_ci    while (1) {
10627b27ec6Sopenharmony_ci        ret = LZ4F_read(lz4fRead, buf, CHUNK_SIZE);
10727b27ec6Sopenharmony_ci        if (LZ4F_isError(ret)) {
10827b27ec6Sopenharmony_ci            printf("LZ4F_read error: %s\n", LZ4F_getErrorName(ret));
10927b27ec6Sopenharmony_ci            goto out;
11027b27ec6Sopenharmony_ci        }
11127b27ec6Sopenharmony_ci
11227b27ec6Sopenharmony_ci        /* nothing to read */
11327b27ec6Sopenharmony_ci        if (ret == 0) {
11427b27ec6Sopenharmony_ci            break;
11527b27ec6Sopenharmony_ci        }
11627b27ec6Sopenharmony_ci
11727b27ec6Sopenharmony_ci        if(fwrite(buf, 1, ret, f_out) != ret) {
11827b27ec6Sopenharmony_ci            printf("write error!\n");
11927b27ec6Sopenharmony_ci            goto out;
12027b27ec6Sopenharmony_ci        }
12127b27ec6Sopenharmony_ci    }
12227b27ec6Sopenharmony_ci
12327b27ec6Sopenharmony_ciout:
12427b27ec6Sopenharmony_ci    free(buf);
12527b27ec6Sopenharmony_ci    if (LZ4F_isError(LZ4F_readClose(lz4fRead))) {
12627b27ec6Sopenharmony_ci        printf("LZ4F_readClose: %s\n", LZ4F_getErrorName(ret));
12727b27ec6Sopenharmony_ci        return 1;
12827b27ec6Sopenharmony_ci    }
12927b27ec6Sopenharmony_ci
13027b27ec6Sopenharmony_ci    if (ret) {
13127b27ec6Sopenharmony_ci        return 1;
13227b27ec6Sopenharmony_ci    }
13327b27ec6Sopenharmony_ci
13427b27ec6Sopenharmony_ci    return 0;
13527b27ec6Sopenharmony_ci}
13627b27ec6Sopenharmony_ci
13727b27ec6Sopenharmony_ciint compareFiles(FILE* fp0, FILE* fp1)
13827b27ec6Sopenharmony_ci{
13927b27ec6Sopenharmony_ci    int result = 0;
14027b27ec6Sopenharmony_ci
14127b27ec6Sopenharmony_ci    while (result==0) {
14227b27ec6Sopenharmony_ci        char b0[1024];
14327b27ec6Sopenharmony_ci        char b1[1024];
14427b27ec6Sopenharmony_ci        size_t const r0 = fread(b0, 1, sizeof(b0), fp0);
14527b27ec6Sopenharmony_ci        size_t const r1 = fread(b1, 1, sizeof(b1), fp1);
14627b27ec6Sopenharmony_ci
14727b27ec6Sopenharmony_ci        result = (r0 != r1);
14827b27ec6Sopenharmony_ci        if (!r0 || !r1) break;
14927b27ec6Sopenharmony_ci        if (!result) result = memcmp(b0, b1, r0);
15027b27ec6Sopenharmony_ci    }
15127b27ec6Sopenharmony_ci
15227b27ec6Sopenharmony_ci    return result;
15327b27ec6Sopenharmony_ci}
15427b27ec6Sopenharmony_ci
15527b27ec6Sopenharmony_ciint main(int argc, const char **argv) {
15627b27ec6Sopenharmony_ci    char inpFilename[256] = { 0 };
15727b27ec6Sopenharmony_ci    char lz4Filename[256] = { 0 };
15827b27ec6Sopenharmony_ci    char decFilename[256] = { 0 };
15927b27ec6Sopenharmony_ci
16027b27ec6Sopenharmony_ci    if (argc < 2) {
16127b27ec6Sopenharmony_ci        printf("Please specify input filename\n");
16227b27ec6Sopenharmony_ci        return 0;
16327b27ec6Sopenharmony_ci    }
16427b27ec6Sopenharmony_ci
16527b27ec6Sopenharmony_ci    snprintf(inpFilename, 256, "%s", argv[1]);
16627b27ec6Sopenharmony_ci    snprintf(lz4Filename, 256, "%s.lz4", argv[1]);
16727b27ec6Sopenharmony_ci    snprintf(decFilename, 256, "%s.lz4.dec", argv[1]);
16827b27ec6Sopenharmony_ci
16927b27ec6Sopenharmony_ci    printf("inp = [%s]\n", inpFilename);
17027b27ec6Sopenharmony_ci    printf("lz4 = [%s]\n", lz4Filename);
17127b27ec6Sopenharmony_ci    printf("dec = [%s]\n", decFilename);
17227b27ec6Sopenharmony_ci
17327b27ec6Sopenharmony_ci    /* compress */
17427b27ec6Sopenharmony_ci    {   FILE* const inpFp = fopen(inpFilename, "rb");
17527b27ec6Sopenharmony_ci        FILE* const outFp = fopen(lz4Filename, "wb");
17627b27ec6Sopenharmony_ci        printf("compress : %s -> %s\n", inpFilename, lz4Filename);
17727b27ec6Sopenharmony_ci        LZ4F_errorCode_t ret = compress_file(inpFp, outFp);
17827b27ec6Sopenharmony_ci        fclose(inpFp);
17927b27ec6Sopenharmony_ci        fclose(outFp);
18027b27ec6Sopenharmony_ci
18127b27ec6Sopenharmony_ci        if (ret) {
18227b27ec6Sopenharmony_ci            printf("compression error: %s\n", LZ4F_getErrorName(ret));
18327b27ec6Sopenharmony_ci            return 1;
18427b27ec6Sopenharmony_ci        }
18527b27ec6Sopenharmony_ci
18627b27ec6Sopenharmony_ci        printf("%s: %zu → %zu bytes, %.1f%%\n",
18727b27ec6Sopenharmony_ci            inpFilename,
18827b27ec6Sopenharmony_ci            get_file_size(inpFilename),
18927b27ec6Sopenharmony_ci            get_file_size(lz4Filename), /* might overflow is size_t is 32 bits and size_{in,out} > 4 GB */
19027b27ec6Sopenharmony_ci            (double)get_file_size(lz4Filename) / get_file_size(inpFilename) * 100);
19127b27ec6Sopenharmony_ci
19227b27ec6Sopenharmony_ci        printf("compress : done\n");
19327b27ec6Sopenharmony_ci    }
19427b27ec6Sopenharmony_ci
19527b27ec6Sopenharmony_ci    /* decompress */
19627b27ec6Sopenharmony_ci    {
19727b27ec6Sopenharmony_ci        FILE* const inpFp = fopen(lz4Filename, "rb");
19827b27ec6Sopenharmony_ci        FILE* const outFp = fopen(decFilename, "wb");
19927b27ec6Sopenharmony_ci
20027b27ec6Sopenharmony_ci        printf("decompress : %s -> %s\n", lz4Filename, decFilename);
20127b27ec6Sopenharmony_ci        LZ4F_errorCode_t ret = decompress_file(inpFp, outFp);
20227b27ec6Sopenharmony_ci
20327b27ec6Sopenharmony_ci        fclose(outFp);
20427b27ec6Sopenharmony_ci        fclose(inpFp);
20527b27ec6Sopenharmony_ci
20627b27ec6Sopenharmony_ci        if (ret) {
20727b27ec6Sopenharmony_ci            printf("compression error: %s\n", LZ4F_getErrorName(ret));
20827b27ec6Sopenharmony_ci            return 1;
20927b27ec6Sopenharmony_ci        }
21027b27ec6Sopenharmony_ci
21127b27ec6Sopenharmony_ci        printf("decompress : done\n");
21227b27ec6Sopenharmony_ci    }
21327b27ec6Sopenharmony_ci
21427b27ec6Sopenharmony_ci    /* verify */
21527b27ec6Sopenharmony_ci    {   FILE* const inpFp = fopen(inpFilename, "rb");
21627b27ec6Sopenharmony_ci        FILE* const decFp = fopen(decFilename, "rb");
21727b27ec6Sopenharmony_ci
21827b27ec6Sopenharmony_ci        printf("verify : %s <-> %s\n", inpFilename, decFilename);
21927b27ec6Sopenharmony_ci        int const cmp = compareFiles(inpFp, decFp);
22027b27ec6Sopenharmony_ci
22127b27ec6Sopenharmony_ci        fclose(decFp);
22227b27ec6Sopenharmony_ci        fclose(inpFp);
22327b27ec6Sopenharmony_ci
22427b27ec6Sopenharmony_ci        if (cmp) {
22527b27ec6Sopenharmony_ci            printf("corruption detected : decompressed file differs from original\n");
22627b27ec6Sopenharmony_ci            return cmp;
22727b27ec6Sopenharmony_ci        }
22827b27ec6Sopenharmony_ci
22927b27ec6Sopenharmony_ci        printf("verify : OK\n");
23027b27ec6Sopenharmony_ci    }
23127b27ec6Sopenharmony_ci
23227b27ec6Sopenharmony_ci}
233