summaryrefslogtreecommitdiffstats
path: root/examples/frameCompress.c
diff options
context:
space:
mode:
authorYann Collet <cyan@fb.com>2018-01-31 22:33:16 (GMT)
committerYann Collet <cyan@fb.com>2018-01-31 22:33:16 (GMT)
commit87fb7a1d031a7e6df72d5ca50ab543a57ddca21f (patch)
tree4fb328b79a82c18cbb458e677681b80b40bb03d5 /examples/frameCompress.c
parent8258f4d9cba4c163f0c63a60a79d14d8aef90c4e (diff)
downloadlz4-87fb7a1d031a7e6df72d5ca50ab543a57ddca21f.zip
lz4-87fb7a1d031a7e6df72d5ca50ab543a57ddca21f.tar.gz
lz4-87fb7a1d031a7e6df72d5ca50ab543a57ddca21f.tar.bz2
refactored frameCompress example
to better reflect LZ4F API usage.
Diffstat (limited to 'examples/frameCompress.c')
-rw-r--r--examples/frameCompress.c150
1 files changed, 82 insertions, 68 deletions
diff --git a/examples/frameCompress.c b/examples/frameCompress.c
index d66a8dc..35dbde2 100644
--- a/examples/frameCompress.c
+++ b/examples/frameCompress.c
@@ -1,122 +1,133 @@
-// LZ4frame API example : compress a file
-// Based on sample code from Zbigniew Jędrzejewski-Szmek
+/* LZ4frame API example : compress a file
+ * Based on sample code from Zbigniew Jędrzejewski-Szmek
+ *
+ * This example streams an input file into an output file
+ * using a bounded memory budget.
+ * Input is read in chunks of IN_CHUNK_SIZE */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <assert.h>
#include <lz4frame.h>
-#define BUF_SIZE 16*1024
-#define LZ4_HEADER_SIZE 19
-#define LZ4_FOOTER_SIZE 4
+
+#define IN_CHUNK_SIZE (16*1024)
static const LZ4F_preferences_t lz4_preferences = {
{ LZ4F_max256KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame,
- 0 /* content size unknown */, 0 /* no dictID */ , LZ4F_noBlockChecksum },
- 0, /* compression level */
+ 0 /* unknown content size */, 0 /* no dictID */ , LZ4F_noBlockChecksum },
+ 0, /* compression level; 0 == default */
0, /* autoflush */
{ 0, 0, 0, 0 }, /* reserved, must be set to 0 */
};
-static size_t compress_file(FILE *in, FILE *out, size_t *size_in, size_t *size_out) {
- size_t r=1; /* function result; 1 == error, default (early exit) */
- LZ4F_compressionContext_t ctx;
- char *src, *buf = NULL;
- size_t size, count_in = 0, count_out, offset = 0, frame_size;
+/* safe_fwrite() :
+ * performs fwrite(), ensure operation success, or immediately exit() */
+static void safe_fwrite(void* buf, size_t eltSize, size_t nbElt, FILE* f)
+{
+ size_t const writtenSize = fwrite(buf, eltSize, nbElt, f);
+ size_t const expectedSize = eltSize * nbElt; /* note : should check for overflow */
+ if (writtenSize < expectedSize) {
+ if (ferror(f)) /* note : ferror() must follow fwrite */
+ printf("Write failed\n");
+ else
+ printf("Short write\n");
+ exit(1);
+ }
+}
+
+
+static size_t
+compress_file(FILE* in, FILE* out,
+ unsigned long long* size_in,
+ unsigned long long* size_out)
+{
+ size_t result = 1; /* function result; 1 == error, default (early exit) */
+ unsigned long long count_in = 0, count_out;
+
+ /* init */
+ LZ4F_compressionContext_t ctx;
if (LZ4F_isError( LZ4F_createCompressionContext(&ctx, LZ4F_VERSION) )) {
- printf("Failed to create context: error %zu\n", r);
- return 1;
+ printf("error: failed to create context \n");
+ return result;
}
- src = malloc(BUF_SIZE);
+ char* outbuff = NULL;
+ void* const src = malloc(IN_CHUNK_SIZE);
if (!src) {
printf("Not enough memory\n");
goto cleanup;
}
- frame_size = LZ4F_compressBound(BUF_SIZE, &lz4_preferences);
- size = frame_size + LZ4_HEADER_SIZE + LZ4_FOOTER_SIZE;
- buf = malloc(size);
- if (!buf) {
+ size_t const outbufCapacity = LZ4F_compressBound(IN_CHUNK_SIZE, &lz4_preferences); /* large enough for any input <= IN_CHUNK_SIZE */
+ outbuff = malloc(outbufCapacity);
+ if (!outbuff) {
printf("Not enough memory\n");
goto cleanup;
}
- { size_t const headerSize = LZ4F_compressBegin(ctx, buf, size, &lz4_preferences);
+ /* write frame header */
+ assert(outbufCapacity >= LZ4F_HEADER_SIZE_MAX);
+ { size_t const headerSize = LZ4F_compressBegin(ctx, outbuff, outbufCapacity, &lz4_preferences);
if (LZ4F_isError(headerSize)) {
printf("Failed to start compression: error %zu\n", headerSize);
goto cleanup;
}
- offset = count_out = headerSize;
- printf("Buffer size is %zu bytes, header size %zu bytes\n", size, headerSize);
+ count_out = headerSize;
+ printf("Buffer size is %zu bytes, header size %zu bytes\n", outbufCapacity, headerSize);
+ safe_fwrite(outbuff, 1, headerSize, out);
}
-
+ /* stream file */
for (;;) {
- size_t const readSize = fread(src, 1, BUF_SIZE, in);
- if (readSize == 0)
- break;
+ size_t const readSize = fread(src, 1, outbufCapacity, in);
+ if (readSize == 0) break;
count_in += readSize;
- { size_t const compressedSize = LZ4F_compressUpdate(ctx, buf + offset, size - offset, src, readSize, NULL);
- if (LZ4F_isError(compressedSize)) {
- printf("Compression failed: error %zu\n", compressedSize);
- goto cleanup;
- }
- offset += compressedSize;
- count_out += compressedSize;
+ size_t const compressedSize = LZ4F_compressUpdate(ctx,
+ outbuff, outbufCapacity,
+ src, readSize,
+ NULL);
+ if (LZ4F_isError(compressedSize)) {
+ printf("Compression failed: error %zu\n", compressedSize);
+ goto cleanup;
}
- if (size - offset < frame_size + LZ4_FOOTER_SIZE) {
- size_t writtenSize;
- printf("Writing %zu bytes\n", offset);
-
- writtenSize = fwrite(buf, 1, offset, out);
- if (writtenSize < offset) {
- if (ferror(out)) /* note : ferror() must follow fwrite */
- printf("Write failed\n");
- else
- printf("Short write\n");
- goto cleanup;
- }
-
- offset = 0;
- }
+ printf("Writing %zu bytes\n", compressedSize);
+ safe_fwrite(outbuff, 1, compressedSize, out);
+ count_out += compressedSize;
}
- { size_t const compressedSize = LZ4F_compressEnd(ctx, buf + offset, size - offset, NULL);
+ /* flush whatever remains within internal buffers */
+ { size_t const compressedSize = LZ4F_compressEnd(ctx,
+ outbuff, outbufCapacity,
+ NULL);
if (LZ4F_isError(compressedSize)) {
printf("Failed to end compression: error %zu\n", compressedSize);
goto cleanup;
}
- offset += compressedSize;
+
+ printf("Writing %zu bytes\n", compressedSize);
+ safe_fwrite(outbuff, 1, compressedSize, out);
count_out += compressedSize;
}
- printf("Writing %zu bytes\n", offset);
- { size_t const writtenSize = fwrite(buf, 1, offset, out);
- if (writtenSize < offset) {
- if (ferror(out))
- printf("Write failed\n");
- else
- printf("Short write\n");
- goto cleanup;
- } }
-
*size_in = count_in;
*size_out = count_out;
- r = 0; /* success */
+ result = 0; /* success */
cleanup:
LZ4F_freeCompressionContext(ctx); /* supports free on NULL */
free(src);
- free(buf);
- return r;
+ free(outbuff);
+ return result;
}
+
static size_t get_block_size(const LZ4F_frameInfo_t* info) {
switch (info->blockSizeID) {
case LZ4F_default:
@@ -131,7 +142,7 @@ static size_t get_block_size(const LZ4F_frameInfo_t* info) {
}
static size_t decompress_file(FILE* in, FILE* out) {
- void* const src = malloc(BUF_SIZE);
+ void* const src = malloc(IN_CHUNK_SIZE);
void* dst = NULL;
size_t dstCapacity = 0;
LZ4F_dctx* dctx = NULL;
@@ -148,7 +159,7 @@ static size_t decompress_file(FILE* in, FILE* out) {
/* Decompression */
while (ret != 0) {
/* Load more input */
- size_t srcSize = fread(src, 1, BUF_SIZE, in);
+ size_t srcSize = fread(src, 1, IN_CHUNK_SIZE, in);
const void* srcPtr = src;
const void* const srcEnd = srcPtr + srcSize;
if (srcSize == 0 || ferror(in)) {
@@ -215,6 +226,7 @@ cleanup:
return LZ4F_freeDecompressionContext(dctx); /* note : free works on NULL */
}
+
int compare(FILE* fp0, FILE* fp1)
{
int result = 0;
@@ -238,6 +250,7 @@ int compare(FILE* fp0, FILE* fp1)
return result;
}
+
int main(int argc, const char **argv) {
char inpFilename[256] = { 0 };
char lz4Filename[256] = { 0 };
@@ -259,8 +272,8 @@ int main(int argc, const char **argv) {
/* compress */
{ FILE* const inpFp = fopen(inpFilename, "rb");
FILE* const outFp = fopen(lz4Filename, "wb");
- size_t sizeIn = 0;
- size_t sizeOut = 0;
+ unsigned long long sizeIn = 0;
+ unsigned long long sizeOut = 0;
size_t ret;
printf("compress : %s -> %s\n", inpFilename, lz4Filename);
@@ -270,7 +283,8 @@ int main(int argc, const char **argv) {
return (int)ret;
}
printf("%s: %zu → %zu bytes, %.1f%%\n",
- inpFilename, sizeIn, sizeOut,
+ inpFilename,
+ (size_t)sizeIn, (size_t)sizeOut, /* might overflow */
(double)sizeOut / sizeIn * 100);
printf("compress : done\n");