From 7f975c0c2881c1f6b2523fdc64489cda280c6de1 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Thu, 13 Dec 2018 15:42:55 -0800 Subject: [PATCH 01/10] create simple_compressionCCtx.c out of simple_compression.c, to be worked on --- examples/simple_compressionCCtx.c | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 examples/simple_compressionCCtx.c diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c new file mode 100644 index 000000000..0193dd40f --- /dev/null +++ b/examples/simple_compressionCCtx.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include // malloc, free, exit +#include // fprintf, perror, fopen, etc. +#include // strlen, strcat, memset, strerror +#include // errno +#include // stat +#include // presumes zstd library is installed +#include "utils.h" + +static void compress_orDie(const char* fname, const char* oname) +{ + size_t fSize; + void* const fBuff = loadFile_orDie(fname, &fSize); + size_t const cBuffSize = ZSTD_compressBound(fSize); + void* const cBuff = malloc_orDie(cBuffSize); + + size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1); + if (ZSTD_isError(cSize)) { + fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); + exit(8); + } + + saveFile_orDie(oname, cBuff, cSize); + + /* success */ + printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); + + free(fBuff); + free(cBuff); +} + +static char* createOutFilename_orDie(const char* filename) +{ + size_t const inL = strlen(filename); + size_t const outL = inL + 5; + void* const outSpace = malloc_orDie(outL); + memset(outSpace, 0, outL); + strcat(outSpace, filename); + strcat(outSpace, ".zst"); + return (char*)outSpace; +} + +int main(int argc, const char** argv) +{ + const char* const exeName = argv[0]; + + if (argc!=2) { + printf("wrong arguments\n"); + printf("usage:\n"); + printf("%s FILE\n", exeName); + return 1; + } + + const char* const inFilename = argv[1]; + + char* const outFilename = createOutFilename_orDie(inFilename); + compress_orDie(inFilename, outFilename); + free(outFilename); + return 0; +} From 193fbd30f236ddee04d85aece12465b13aa10335 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Thu, 13 Dec 2018 22:51:35 -0800 Subject: [PATCH 02/10] WIP --- examples/simple_compressionCCtx.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c index 0193dd40f..17255cba2 100644 --- a/examples/simple_compressionCCtx.c +++ b/examples/simple_compressionCCtx.c @@ -62,6 +62,17 @@ int main(int argc, const char** argv) const char* const inFilename = argv[1]; + /** copied code + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } + size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict); + if (ZSTD_isError(cSize)) { + fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); + exit(7); + } + **/ + + char* const outFilename = createOutFilename_orDie(inFilename); compress_orDie(inFilename, outFilename); free(outFilename); From 04d06ad8850c77f60e936e6a1c8eb0de6146a8cc Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Fri, 14 Dec 2018 18:12:05 -0800 Subject: [PATCH 03/10] refactor utils.h and implement simple_compressionCCtx.c --- examples/.gitignore | 1 + examples/Makefile | 6 +++ examples/dictionary_compression.c | 4 +- examples/dictionary_decompression.c | 4 +- examples/simple_compression.c | 2 +- examples/simple_compressionCCtx.c | 75 ++++++++++++++++----------- examples/simple_decompression.c | 2 +- examples/utils.h | 80 +++++++++++++++++------------ 8 files changed, 106 insertions(+), 68 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index 280feb36e..c92c69897 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,6 +1,7 @@ #build simple_compression simple_decompression +simple_compressionCCtx dictionary_compression dictionary_decompression streaming_compression diff --git a/examples/Makefile b/examples/Makefile index 96af41b54..7bcbd120b 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -17,6 +17,7 @@ LIB = ../lib/libzstd.a default: all all: simple_compression simple_decompression \ + simple_compressionCCtx\ dictionary_compression dictionary_decompression \ streaming_compression streaming_decompression \ multiple_streaming_compression streaming_memory_usage @@ -30,6 +31,9 @@ simple_compression : simple_compression.c $(LIB) simple_decompression : simple_decompression.c $(LIB) $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +simple_compressionCCtx : simple_compressionCCtx.c $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ + dictionary_compression : dictionary_compression.c $(LIB) $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ @@ -51,6 +55,7 @@ streaming_memory_usage : streaming_memory_usage.c $(LIB) clean: @rm -f core *.o tmp* result* *.zst \ simple_compression simple_decompression \ + simple_compressionCCtx \ dictionary_compression dictionary_decompression \ streaming_compression streaming_decompression \ multiple_streaming_compression streaming_memory_usage @@ -62,6 +67,7 @@ test: all @echo -- Simple compression tests ./simple_compression tmp ./simple_decompression tmp.zst + ./simple_compressionCCtx *.c ./streaming_decompression tmp.zst > /dev/null @echo -- Streaming memory usage ./streaming_memory_usage diff --git a/examples/dictionary_compression.c b/examples/dictionary_compression.c index 511b35676..2a3d61562 100644 --- a/examples/dictionary_compression.c +++ b/examples/dictionary_compression.c @@ -21,7 +21,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel) { size_t dictSize; printf("loading dictionary %s \n", dictFileName); - void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize); + void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize, 0, 0); ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel); if (!cdict) { fprintf(stderr, "ZSTD_createCDict error \n"); @@ -35,7 +35,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel) static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdict) { size_t fSize; - void* const fBuff = loadFile_orDie(fname, &fSize); + void* const fBuff = loadFile_orDie(fname, &fSize, 0, 0); size_t const cBuffSize = ZSTD_compressBound(fSize); void* const cBuff = malloc_orDie(cBuffSize); diff --git a/examples/dictionary_decompression.c b/examples/dictionary_decompression.c index 69f56d56b..36d20c1b1 100644 --- a/examples/dictionary_decompression.c +++ b/examples/dictionary_decompression.c @@ -25,7 +25,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName) { size_t dictSize; printf("loading dictionary %s \n", dictFileName); - void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize); + void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize, 0, 0); ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize); if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); } free(dictBuffer); @@ -35,7 +35,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName) static void decompress(const char* fname, const ZSTD_DDict* ddict) { size_t cSize; - void* const cBuff = loadFile_orDie(fname, &cSize); + void* const cBuff = loadFile_orDie(fname, &cSize, 0, 0); unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); if (rSize==ZSTD_CONTENTSIZE_ERROR) { fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); diff --git a/examples/simple_compression.c b/examples/simple_compression.c index 0193dd40f..7f1fa6cc6 100644 --- a/examples/simple_compression.c +++ b/examples/simple_compression.c @@ -19,7 +19,7 @@ static void compress_orDie(const char* fname, const char* oname) { size_t fSize; - void* const fBuff = loadFile_orDie(fname, &fSize); + void* const fBuff = loadFile_orDie(fname, &fSize, 0, 0); size_t const cBuffSize = ZSTD_compressBound(fSize); void* const cBuff = malloc_orDie(cBuffSize); diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c index 17255cba2..a5447f069 100644 --- a/examples/simple_compressionCCtx.c +++ b/examples/simple_compressionCCtx.c @@ -16,14 +16,14 @@ #include // presumes zstd library is installed #include "utils.h" -static void compress_orDie(const char* fname, const char* oname) +/* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/ +static void compressExpress_orDie(const char* fname, const char* oname, + ZSTD_CCtx* cctx, void* cBuff, size_t cBuffSize, void* fBuff, size_t fBuffSize) { size_t fSize; - void* const fBuff = loadFile_orDie(fname, &fSize); - size_t const cBuffSize = ZSTD_compressBound(fSize); - void* const cBuff = malloc_orDie(cBuffSize); + loadFile_orDie(fname, &fSize, fBuff, fBuffSize); - size_t const cSize = ZSTD_compress(cBuff, cBuffSize, fBuff, fSize, 1); + size_t const cSize = ZSTD_compressCCtx(cctx, cBuff, cBuffSize, fBuff, fBuffSize, 1); if (ZSTD_isError(cSize)) { fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); exit(8); @@ -33,48 +33,65 @@ static void compress_orDie(const char* fname, const char* oname) /* success */ printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); - - free(fBuff); - free(cBuff); } -static char* createOutFilename_orDie(const char* filename) +static void getOutFilename(const char* const filename, char* const outFilename) { - size_t const inL = strlen(filename); - size_t const outL = inL + 5; - void* const outSpace = malloc_orDie(outL); - memset(outSpace, 0, outL); - strcat(outSpace, filename); - strcat(outSpace, ".zst"); - return (char*)outSpace; + memset(outFilename, 0, 1); + strcat(outFilename, filename); + strcat(outFilename, ".zst"); } int main(int argc, const char** argv) { const char* const exeName = argv[0]; - if (argc!=2) { + if (argc<2) { printf("wrong arguments\n"); printf("usage:\n"); - printf("%s FILE\n", exeName); + printf("%s FILE(s)\n", exeName); return 1; } - const char* const inFilename = argv[1]; + /* pre-calculate buffer sizes needed to handle all files */ + size_t maxFileNameLength=0; + size_t maxFileSize = 0; + size_t maxCBufferSize = 0; - /** copied code - ZSTD_CCtx* const cctx = ZSTD_createCCtx(); - if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } - size_t const cSize = ZSTD_compress_usingCDict(cctx, cBuff, cBuffSize, fBuff, fSize, cdict); - if (ZSTD_isError(cSize)) { - fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); - exit(7); + int argNb; + for (argNb = 1; argNb < argc; argNb++) { + const char* const fileName = argv[argNb]; + size_t const fileNameLength = strlen(fileName); + size_t const fileSize = fsize_orDie(fileName); + + if (fileNameLength > maxFileNameLength) maxFileNameLength = fileNameLength; + if (fileSize > maxFileSize) maxFileSize = fileSize; } - **/ + maxCBufferSize = ZSTD_compressBound(maxFileSize); + /* allocate memory for output file name, input/output buffers for all compression tasks */ + char* const outFilename = (char*)malloc_orDie(maxFileNameLength + 5); + void* const fBuffer = malloc_orDie(maxFileSize); + void* const cBuffer = malloc_orDie(maxCBufferSize); - char* const outFilename = createOutFilename_orDie(inFilename); - compress_orDie(inFilename, outFilename); + /* create a compression context (ZSTD_CCtx) for all compression tasks */ + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } + + /* compress files with shared context, input and output buffers */ + for (argNb = 1; argNb < argc; argNb++) { + const char* const inFilename = argv[argNb]; + getOutFilename(inFilename, outFilename); + compressExpress_orDie(inFilename, outFilename, cctx, cBuffer, maxCBufferSize, fBuffer, maxFileSize); + } + + /* free momery resources */ free(outFilename); + free(fBuffer); + free(cBuffer); + ZSTD_freeCCtx(cctx); /* never fails */ + + printf("compressed %i files \n", argc-1); + return 0; } diff --git a/examples/simple_decompression.c b/examples/simple_decompression.c index ee055dd67..00e020954 100644 --- a/examples/simple_decompression.c +++ b/examples/simple_decompression.c @@ -20,7 +20,7 @@ static void decompress(const char* fname) { size_t cSize; - void* const cBuff = loadFile_orDie(fname, &cSize); + void* const cBuff = loadFile_orDie(fname, &cSize, 0, 0); unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); if (rSize==ZSTD_CONTENTSIZE_ERROR) { fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); diff --git a/examples/utils.h b/examples/utils.h index 55a329e23..506cc1ab4 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -9,7 +9,7 @@ */ /* - * This header file has common utility functions used in examples. + * This header file has common utility functions used in examples. */ #ifndef UTILS_H #define UTILS_H @@ -21,7 +21,7 @@ #include // stat /* - * Define the returned error code from utility functions. + * Define the returned error code from utility functions. */ typedef enum { ERROR_fsize = 1, @@ -35,21 +35,33 @@ typedef enum { ERROR_largeFile = 9, } UTILS_ErrorCode; -/*! fsize_orDie() : +/*! fsize_orDie() : * Get the size of a given file path. - * + * * @return The size of a given file path. */ -static off_t fsize_orDie(const char *filename) +static size_t fsize_orDie(const char *filename) { struct stat st; - if (stat(filename, &st) == 0) return st.st_size; - /* error */ - perror(filename); - exit(ERROR_fsize); + if (stat(filename, &st) != 0) { + /* error */ + perror(filename); + exit(ERROR_fsize); + } + + off_t const fileSize = st.st_size; + size_t const size = (size_t)fileSize; + /* if off_t -> size_t conversion causes discrepancy, the file size is + * too big for at least 1 type to handle + */ + if (size != fileSize) { /* narrowcast overflow */ + fprintf(stderr, "%s : filesize too large \n", filename); + exit(ERROR_largeFile); + } + return size; } -/*! fopen_orDie() : +/*! fopen_orDie() : * Open a file using given file path and open option. * * @return If successful this function will return a FILE pointer to an @@ -64,7 +76,7 @@ static FILE* fopen_orDie(const char *filename, const char *instruction) exit(ERROR_fopen); } -/*! fclose_orDie() : +/*! fclose_orDie() : * Close an opened file using given FILE pointer. */ static void fclose_orDie(FILE* file) @@ -75,11 +87,11 @@ static void fclose_orDie(FILE* file) exit(ERROR_fclose); } -/*! fread_orDie() : - * +/*! fread_orDie() : + * * Read sizeToRead bytes from a given file, storing them at the * location given by buffer. - * + * * @return The number of bytes read. */ static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file) @@ -93,12 +105,12 @@ static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file) } /*! fwrite_orDie() : - * + * * Write sizeToWrite bytes to a file pointed to by file, obtaining * them from a location given by buffer. * * Note: This function will send an error to stderr and exit if it - * cannot write data to the given file pointer. + * cannot write data to the given file pointer. * * @return The number of bytes written. */ @@ -113,7 +125,7 @@ static size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file) /*! malloc_orDie() : * Allocate memory. - * + * * @return If successful this function returns a pointer to allo- * cated memory. If there is an error, this function will send that * error to stderr and exit. @@ -128,39 +140,41 @@ static void* malloc_orDie(size_t size) } /*! loadFile_orDie() : - * Read size bytes from a file. - * + * Read size bytes from a file. If buffer is not provided (i.e., buffer == null), + * malloc will be called to allocate one. + * * Note: This function will send an error to stderr and exit if it * cannot read data from the given file path. - * + * * @return If successful this function will return a pointer to read * data otherwise it will printout an error to stderr and exit. */ -static void* loadFile_orDie(const char* fileName, size_t* size) +static void* loadFile_orDie(const char* fileName, size_t* size, void* buffer, int bufferSize) { - off_t const fileSize = fsize_orDie(fileName); - size_t const buffSize = (size_t)fileSize; - if ((off_t)buffSize < fileSize) { /* narrowcast overflow */ - fprintf(stderr, "%s : filesize too large \n", fileName); - exit(ERROR_largeFile); - } + size_t const fileSize = fsize_orDie(fileName); FILE* const inFile = fopen_orDie(fileName, "rb"); - void* const buffer = malloc_orDie(buffSize); - size_t const readSize = fread(buffer, 1, buffSize, inFile); - if (readSize != (size_t)buffSize) { + if (!buffer) { + buffer = malloc_orDie(fileSize); + } + else if (bufferSize < fileSize) { + fprintf(stderr, "%s : filesize bigger than provided buffer.\n", fileName); + + } + size_t const readSize = fread(buffer, 1, fileSize, inFile); + if (readSize != (size_t)fileSize) { fprintf(stderr, "fread: %s : %s \n", fileName, strerror(errno)); exit(ERROR_fread); } fclose(inFile); /* can't fail, read only */ - *size = buffSize; + *size = fileSize; return buffer; } /*! saveFile_orDie() : - * + * * Save buffSize bytes to a given file path, obtaining them from a location pointed * to by buff. - * + * * Note: This function will send an error to stderr and exit if it * cannot write to a given file. */ From 0d14153cfb52fb8d24fcfe956498edc50a02764d Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Fri, 14 Dec 2018 22:10:31 -0800 Subject: [PATCH 04/10] formatting --- examples/simple_compressionCCtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c index a5447f069..d3dd67cc7 100644 --- a/examples/simple_compressionCCtx.c +++ b/examples/simple_compressionCCtx.c @@ -18,7 +18,7 @@ /* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/ static void compressExpress_orDie(const char* fname, const char* oname, - ZSTD_CCtx* cctx, void* cBuff, size_t cBuffSize, void* fBuff, size_t fBuffSize) + ZSTD_CCtx* cctx, void* cBuff, size_t cBuffSize, void* fBuff, size_t fBuffSize) { size_t fSize; loadFile_orDie(fname, &fSize, fBuff, fBuffSize); From cce0842c607de31320a4fd37c1218fd40ac9b011 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Sun, 16 Dec 2018 15:36:28 -0800 Subject: [PATCH 05/10] Factor out allocMemory_orDIe(...) in simple_compressionCCtx.c, and amend Makefile to account for dependency on utils.h --- examples/Makefile | 34 ++++++++--------- examples/simple_compressionCCtx.c | 62 ++++++++++++++++++++----------- examples/utils.h | 4 +- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 7bcbd120b..7af6176b1 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -25,32 +25,32 @@ all: simple_compression simple_decompression \ $(LIB) : $(MAKE) -C ../lib libzstd.a -simple_compression : simple_compression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +simple_compression : simple_compression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -simple_decompression : simple_decompression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +simple_decompression : simple_decompression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -simple_compressionCCtx : simple_compressionCCtx.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +simple_compressionCCtx : simple_compressionCCtx.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -dictionary_compression : dictionary_compression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +dictionary_compression : dictionary_compression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -dictionary_decompression : dictionary_decompression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +dictionary_decompression : dictionary_decompression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -streaming_compression : streaming_compression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +streaming_compression : streaming_compression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -multiple_streaming_compression : multiple_streaming_compression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +multiple_streaming_compression : multiple_streaming_compression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -streaming_decompression : streaming_decompression.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ +streaming_decompression : streaming_decompression.c utils.h $(LIB) + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ streaming_memory_usage : streaming_memory_usage.c $(LIB) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ $(LDFLAGS) -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ clean: @rm -f core *.o tmp* result* *.zst \ diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c index d3dd67cc7..00279e4e6 100644 --- a/examples/simple_compressionCCtx.c +++ b/examples/simple_compressionCCtx.c @@ -23,7 +23,7 @@ static void compressExpress_orDie(const char* fname, const char* oname, size_t fSize; loadFile_orDie(fname, &fSize, fBuff, fBuffSize); - size_t const cSize = ZSTD_compressCCtx(cctx, cBuff, cBuffSize, fBuff, fBuffSize, 1); + size_t const cSize = ZSTD_compressCCtx(cctx, cBuff, cBuffSize, fBuff, fSize, 1); if (ZSTD_isError(cSize)) { fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); exit(8); @@ -42,6 +42,32 @@ static void getOutFilename(const char* const filename, char* const outFilename) strcat(outFilename, ".zst"); } +/* allocate memory for buffers big enough to compress all files + * as well as memory for output file names (outFileName) + */ +void allocMemory_orDie(int argc, const char** argv, char** outFilename, + void** cBuffer, size_t* cBufferSize, void** fBuffer, size_t* fBufferSize) { + size_t maxFilenameLength=0; + size_t maxFileSize = 0; + + int argNb; + for (argNb = 1; argNb < argc; argNb++) { + const char* const filename = argv[argNb]; + size_t const filenameLength = strlen(filename); + size_t const fileSize = fsize_orDie(filename); + + if (filenameLength > maxFilenameLength) maxFilenameLength = filenameLength; + if (fileSize > maxFileSize) maxFileSize = fileSize; + } + *cBufferSize = ZSTD_compressBound(maxFileSize); + *fBufferSize = maxFileSize; + + /* allocate memory for output file name, input/output buffers for all compression tasks */ + *outFilename = (char*)malloc_orDie(maxFilenameLength + 5); + *cBuffer = malloc_orDie(*cBufferSize); + *fBuffer = malloc_orDie(*fBufferSize); +} + int main(int argc, const char** argv) { const char* const exeName = argv[0]; @@ -53,36 +79,28 @@ int main(int argc, const char** argv) return 1; } - /* pre-calculate buffer sizes needed to handle all files */ - size_t maxFileNameLength=0; - size_t maxFileSize = 0; - size_t maxCBufferSize = 0; - - int argNb; - for (argNb = 1; argNb < argc; argNb++) { - const char* const fileName = argv[argNb]; - size_t const fileNameLength = strlen(fileName); - size_t const fileSize = fsize_orDie(fileName); - - if (fileNameLength > maxFileNameLength) maxFileNameLength = fileNameLength; - if (fileSize > maxFileSize) maxFileSize = fileSize; - } - maxCBufferSize = ZSTD_compressBound(maxFileSize); - - /* allocate memory for output file name, input/output buffers for all compression tasks */ - char* const outFilename = (char*)malloc_orDie(maxFileNameLength + 5); - void* const fBuffer = malloc_orDie(maxFileSize); - void* const cBuffer = malloc_orDie(maxCBufferSize); + /* allocate memory for buffers big enough to compress all files + * as well as memory for output file name (outFileName) + * fBuffer - buffer for input file data + * cBuffer - buffer for compressed data + */ + char* outFilename; + void* fBuffer; + void* cBuffer; + size_t fBufferSize; + size_t cBufferSize; + allocMemory_orDie(argc, argv, &outFilename, &cBuffer, &cBufferSize, &fBuffer, &fBufferSize); /* create a compression context (ZSTD_CCtx) for all compression tasks */ ZSTD_CCtx* const cctx = ZSTD_createCCtx(); if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } /* compress files with shared context, input and output buffers */ + int argNb; for (argNb = 1; argNb < argc; argNb++) { const char* const inFilename = argv[argNb]; getOutFilename(inFilename, outFilename); - compressExpress_orDie(inFilename, outFilename, cctx, cBuffer, maxCBufferSize, fBuffer, maxFileSize); + compressExpress_orDie(inFilename, outFilename, cctx, cBuffer, cBufferSize, fBuffer, fBufferSize); } /* free momery resources */ diff --git a/examples/utils.h b/examples/utils.h index 506cc1ab4..2df52be74 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -51,8 +51,8 @@ static size_t fsize_orDie(const char *filename) off_t const fileSize = st.st_size; size_t const size = (size_t)fileSize; - /* if off_t -> size_t conversion causes discrepancy, the file size is - * too big for at least 1 type to handle + /* if off_t -> size_t type conversion results in discrepancy, + * the file size is too big for at least one type to handle. */ if (size != fileSize) { /* narrowcast overflow */ fprintf(stderr, "%s : filesize too large \n", filename); From ea4859ec7194e1439d1e102f8dee583cbe8cd81b Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Sun, 16 Dec 2018 20:45:43 -0800 Subject: [PATCH 06/10] add multiple_simple_compression.c --- examples/multiple_simple_compression.c | 115 +++++++++++++++++++++++++ examples/utils.h | 7 +- 2 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 examples/multiple_simple_compression.c diff --git a/examples/multiple_simple_compression.c b/examples/multiple_simple_compression.c new file mode 100644 index 000000000..ab128bbb3 --- /dev/null +++ b/examples/multiple_simple_compression.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include // malloc, free, exit +#include // fprintf, perror, fopen, etc. +#include // strlen, strcat, memset, strerror +#include // errno +#include // stat +#include // presumes zstd library is installed +#include "utils.h" + +typedef struct { + void* fBuffer; + void* cBuffer; + size_t fBufferSize; + size_t cBufferSize; + ZSTD_CCtx* cctx; +} resources; + +/* + * allocate memory for buffers big enough to compress all files + * as well as memory for output file name (outFilename) + */ +static resources createResources_orDie(int argc, const char** argv, char **outFilename) +{ + size_t maxFilenameLength=0; + size_t maxFileSize = 0; + + int argNb; + for (argNb = 1; argNb < argc; argNb++) { + const char* const filename = argv[argNb]; + size_t const filenameLength = strlen(filename); + size_t const fileSize = fsize_orDie(filename); + + if (filenameLength > maxFilenameLength) maxFilenameLength = filenameLength; + if (fileSize > maxFileSize) maxFileSize = fileSize; + } + + resources ress; + ress.fBufferSize = maxFileSize; + ress.cBufferSize = ZSTD_compressBound(maxFileSize); + + *outFilename = (char*)malloc_orDie(maxFilenameLength + 5); + ress.fBuffer = malloc_orDie(ress.fBufferSize); + ress.cBuffer = malloc_orDie(ress.cBufferSize); + ress.cctx = ZSTD_createCCtx(); + if (ress.cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } + return ress; +} + +static void freeResources(resources ress, char *outFilename) +{ + free(ress.fBuffer); + free(ress.cBuffer); + ZSTD_freeCCtx(ress.cctx); /* never fails */ + free(outFilename); +} + +/* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/ +static void compressFile_orDie(resources ress, const char* fname, const char* oname) +{ + size_t fSize; + loadFile_orDie(fname, &fSize, ress.fBuffer, ress.fBufferSize); + + size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1); + if (ZSTD_isError(cSize)) { + fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); + exit(8); + } + + saveFile_orDie(oname, ress.cBuffer, cSize); + + /* success */ + printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); +} + +int main(int argc, const char** argv) +{ + const char* const exeName = argv[0]; + + if (argc<2) { + printf("wrong arguments\n"); + printf("usage:\n"); + printf("%s FILE(s)\n", exeName); + return 1; + } + + /* memory allocation for outFilename and resources */ + char* outFilename; + resources ress = createResources_orDie(argc, argv, &outFilename); + + /* compress files with shared context, input and output buffers */ + int argNb; + for (argNb = 1; argNb < argc; argNb++) { + const char* const inFilename = argv[argNb]; + memset(outFilename, 0, 1); + strcat(outFilename, inFilename); + strcat(outFilename, ".zst"); + compressFile_orDie(ress, inFilename, outFilename); + } + + /* free momery */ + freeResources(ress,outFilename); + + printf("compressed %i files \n", argc-1); + + return 0; +} diff --git a/examples/utils.h b/examples/utils.h index 2df52be74..d722d3cef 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -51,10 +51,11 @@ static size_t fsize_orDie(const char *filename) off_t const fileSize = st.st_size; size_t const size = (size_t)fileSize; - /* if off_t -> size_t type conversion results in discrepancy, - * the file size is too big for at least one type to handle. + /* 1. fileSize should be non-negative, + * 2. if off_t -> size_t type conversion results in discrepancy, + * the file size is too large for type size_t. */ - if (size != fileSize) { /* narrowcast overflow */ + if ((fileSize < 0) || (fileSize != (off_t)size)) { fprintf(stderr, "%s : filesize too large \n", filename); exit(ERROR_largeFile); } From 595401e4c7bcd90e6cf8eeefdd0d39302d8840b7 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Sun, 16 Dec 2018 21:09:21 -0800 Subject: [PATCH 07/10] edit README.md and remove simple_compressionCCtx.c --- examples/.gitignore | 2 +- examples/Makefile | 8 +-- examples/README.md | 10 ++- examples/simple_compressionCCtx.c | 115 ------------------------------ 4 files changed, 13 insertions(+), 122 deletions(-) delete mode 100644 examples/simple_compressionCCtx.c diff --git a/examples/.gitignore b/examples/.gitignore index c92c69897..d682cae38 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,7 +1,7 @@ #build simple_compression simple_decompression -simple_compressionCCtx +multiple_simple_compression dictionary_compression dictionary_decompression streaming_compression diff --git a/examples/Makefile b/examples/Makefile index 7af6176b1..25a0a62c2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -17,7 +17,7 @@ LIB = ../lib/libzstd.a default: all all: simple_compression simple_decompression \ - simple_compressionCCtx\ + multiple_simple_compression\ dictionary_compression dictionary_decompression \ streaming_compression streaming_decompression \ multiple_streaming_compression streaming_memory_usage @@ -31,7 +31,7 @@ simple_compression : simple_compression.c utils.h $(LIB) simple_decompression : simple_decompression.c utils.h $(LIB) $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ -simple_compressionCCtx : simple_compressionCCtx.c utils.h $(LIB) +multiple_simple_compression : multiple_simple_compression.c utils.h $(LIB) $(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDFLAGS) -o $@ dictionary_compression : dictionary_compression.c utils.h $(LIB) @@ -55,7 +55,7 @@ streaming_memory_usage : streaming_memory_usage.c $(LIB) clean: @rm -f core *.o tmp* result* *.zst \ simple_compression simple_decompression \ - simple_compressionCCtx \ + multiple_simple_compression \ dictionary_compression dictionary_decompression \ streaming_compression streaming_decompression \ multiple_streaming_compression streaming_memory_usage @@ -67,7 +67,7 @@ test: all @echo -- Simple compression tests ./simple_compression tmp ./simple_decompression tmp.zst - ./simple_compressionCCtx *.c + ./multiple_simple_compression *.c ./streaming_decompression tmp.zst > /dev/null @echo -- Streaming memory usage ./streaming_memory_usage diff --git a/examples/README.md b/examples/README.md index eba50c999..0bff7ac19 100644 --- a/examples/README.md +++ b/examples/README.md @@ -11,8 +11,14 @@ Zstandard library : usage examples Result remains in memory. Introduces usage of : `ZSTD_decompress()` +- [Multiple simple compression](multiple_simple_compression.c) : + Compress multiple files (in simple mode) in a single command line. + Demonstrates memory preservation technique that + minimizes malloc()/free() calls by re-using existing resources. + Introduces usage of : `ZSTD_compressCCtx()` + - [Streaming memory usage](streaming_memory_usage.c) : - Provides amount of memory used by streaming context + Provides amount of memory used by streaming context. Introduces usage of : `ZSTD_sizeof_CStream()` - [Streaming compression](streaming_compression.c) : @@ -20,7 +26,7 @@ Zstandard library : usage examples Introduces usage of : `ZSTD_compressStream()` - [Multiple Streaming compression](multiple_streaming_compression.c) : - Compress multiple files in a single command line. + Compress multiple files (in streaming mode) in a single command line. Introduces memory usage preservation technique, reducing impact of malloc()/free() and memset() by re-using existing resources. diff --git a/examples/simple_compressionCCtx.c b/examples/simple_compressionCCtx.c deleted file mode 100644 index 00279e4e6..000000000 --- a/examples/simple_compressionCCtx.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#include // malloc, free, exit -#include // fprintf, perror, fopen, etc. -#include // strlen, strcat, memset, strerror -#include // errno -#include // stat -#include // presumes zstd library is installed -#include "utils.h" - -/* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/ -static void compressExpress_orDie(const char* fname, const char* oname, - ZSTD_CCtx* cctx, void* cBuff, size_t cBuffSize, void* fBuff, size_t fBuffSize) -{ - size_t fSize; - loadFile_orDie(fname, &fSize, fBuff, fBuffSize); - - size_t const cSize = ZSTD_compressCCtx(cctx, cBuff, cBuffSize, fBuff, fSize, 1); - if (ZSTD_isError(cSize)) { - fprintf(stderr, "error compressing %s : %s \n", fname, ZSTD_getErrorName(cSize)); - exit(8); - } - - saveFile_orDie(oname, cBuff, cSize); - - /* success */ - printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); -} - -static void getOutFilename(const char* const filename, char* const outFilename) -{ - memset(outFilename, 0, 1); - strcat(outFilename, filename); - strcat(outFilename, ".zst"); -} - -/* allocate memory for buffers big enough to compress all files - * as well as memory for output file names (outFileName) - */ -void allocMemory_orDie(int argc, const char** argv, char** outFilename, - void** cBuffer, size_t* cBufferSize, void** fBuffer, size_t* fBufferSize) { - size_t maxFilenameLength=0; - size_t maxFileSize = 0; - - int argNb; - for (argNb = 1; argNb < argc; argNb++) { - const char* const filename = argv[argNb]; - size_t const filenameLength = strlen(filename); - size_t const fileSize = fsize_orDie(filename); - - if (filenameLength > maxFilenameLength) maxFilenameLength = filenameLength; - if (fileSize > maxFileSize) maxFileSize = fileSize; - } - *cBufferSize = ZSTD_compressBound(maxFileSize); - *fBufferSize = maxFileSize; - - /* allocate memory for output file name, input/output buffers for all compression tasks */ - *outFilename = (char*)malloc_orDie(maxFilenameLength + 5); - *cBuffer = malloc_orDie(*cBufferSize); - *fBuffer = malloc_orDie(*fBufferSize); -} - -int main(int argc, const char** argv) -{ - const char* const exeName = argv[0]; - - if (argc<2) { - printf("wrong arguments\n"); - printf("usage:\n"); - printf("%s FILE(s)\n", exeName); - return 1; - } - - /* allocate memory for buffers big enough to compress all files - * as well as memory for output file name (outFileName) - * fBuffer - buffer for input file data - * cBuffer - buffer for compressed data - */ - char* outFilename; - void* fBuffer; - void* cBuffer; - size_t fBufferSize; - size_t cBufferSize; - allocMemory_orDie(argc, argv, &outFilename, &cBuffer, &cBufferSize, &fBuffer, &fBufferSize); - - /* create a compression context (ZSTD_CCtx) for all compression tasks */ - ZSTD_CCtx* const cctx = ZSTD_createCCtx(); - if (cctx==NULL) { fprintf(stderr, "ZSTD_createCCtx() error \n"); exit(10); } - - /* compress files with shared context, input and output buffers */ - int argNb; - for (argNb = 1; argNb < argc; argNb++) { - const char* const inFilename = argv[argNb]; - getOutFilename(inFilename, outFilename); - compressExpress_orDie(inFilename, outFilename, cctx, cBuffer, cBufferSize, fBuffer, fBufferSize); - } - - /* free momery resources */ - free(outFilename); - free(fBuffer); - free(cBuffer); - ZSTD_freeCCtx(cctx); /* never fails */ - - printf("compressed %i files \n", argc-1); - - return 0; -} From a951ee9fe1f157f0e2d611ef9152c146abe1f5bb Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Sun, 16 Dec 2018 21:27:52 -0800 Subject: [PATCH 08/10] comment out printf() to make output terse --- examples/multiple_simple_compression.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multiple_simple_compression.c b/examples/multiple_simple_compression.c index ab128bbb3..2401a99b6 100644 --- a/examples/multiple_simple_compression.c +++ b/examples/multiple_simple_compression.c @@ -78,7 +78,7 @@ static void compressFile_orDie(resources ress, const char* fname, const char* on saveFile_orDie(oname, ress.cBuffer, cSize); /* success */ - printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); + // printf("%25s : %6u -> %7u - %s \n", fname, (unsigned)fSize, (unsigned)cSize, oname); } int main(int argc, const char** argv) From 452689678bf4d956308dc0ad9d3c75440496b4b9 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Sun, 16 Dec 2018 22:44:27 -0800 Subject: [PATCH 09/10] bug fix in loadFile_orDie(): exit with error code if filesize is bigger than provided buffer --- examples/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utils.h b/examples/utils.h index d722d3cef..7968d436f 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -159,7 +159,7 @@ static void* loadFile_orDie(const char* fileName, size_t* size, void* buffer, in } else if (bufferSize < fileSize) { fprintf(stderr, "%s : filesize bigger than provided buffer.\n", fileName); - + exit(ERROR_largeFile); } size_t const readSize = fread(buffer, 1, fileSize, inFile); if (readSize != (size_t)fileSize) { From bc4dc606de284c65162ee8fb9de5c50ab2dfc233 Mon Sep 17 00:00:00 2001 From: Yi Jin Date: Mon, 17 Dec 2018 16:54:55 -0800 Subject: [PATCH 10/10] break loadFile_orDie() into 2: loadFile_orDie() loads file into a pre-allocated memory buffer, mallocAndLoadFile_orDie() allocates memory first, then calls loadFile_orDie() --- examples/dictionary_compression.c | 4 +-- examples/dictionary_decompression.c | 4 +-- examples/multiple_simple_compression.c | 20 +++++++------- examples/simple_compression.c | 2 +- examples/simple_decompression.c | 2 +- examples/utils.h | 37 +++++++++++++++++--------- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/examples/dictionary_compression.c b/examples/dictionary_compression.c index 2a3d61562..3c4a5bd1e 100644 --- a/examples/dictionary_compression.c +++ b/examples/dictionary_compression.c @@ -21,7 +21,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel) { size_t dictSize; printf("loading dictionary %s \n", dictFileName); - void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize, 0, 0); + void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize); ZSTD_CDict* const cdict = ZSTD_createCDict(dictBuffer, dictSize, cLevel); if (!cdict) { fprintf(stderr, "ZSTD_createCDict error \n"); @@ -35,7 +35,7 @@ static ZSTD_CDict* createCDict_orDie(const char* dictFileName, int cLevel) static void compress(const char* fname, const char* oname, const ZSTD_CDict* cdict) { size_t fSize; - void* const fBuff = loadFile_orDie(fname, &fSize, 0, 0); + void* const fBuff = mallocAndLoadFile_orDie(fname, &fSize); size_t const cBuffSize = ZSTD_compressBound(fSize); void* const cBuff = malloc_orDie(cBuffSize); diff --git a/examples/dictionary_decompression.c b/examples/dictionary_decompression.c index 36d20c1b1..243e22236 100644 --- a/examples/dictionary_decompression.c +++ b/examples/dictionary_decompression.c @@ -25,7 +25,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName) { size_t dictSize; printf("loading dictionary %s \n", dictFileName); - void* const dictBuffer = loadFile_orDie(dictFileName, &dictSize, 0, 0); + void* const dictBuffer = mallocAndLoadFile_orDie(dictFileName, &dictSize); ZSTD_DDict* const ddict = ZSTD_createDDict(dictBuffer, dictSize); if (ddict==NULL) { fprintf(stderr, "ZSTD_createDDict error \n"); exit(5); } free(dictBuffer); @@ -35,7 +35,7 @@ static ZSTD_DDict* createDict_orDie(const char* dictFileName) static void decompress(const char* fname, const ZSTD_DDict* ddict) { size_t cSize; - void* const cBuff = loadFile_orDie(fname, &cSize, 0, 0); + void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize); unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); if (rSize==ZSTD_CONTENTSIZE_ERROR) { fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); diff --git a/examples/multiple_simple_compression.c b/examples/multiple_simple_compression.c index 2401a99b6..65c775bfa 100644 --- a/examples/multiple_simple_compression.c +++ b/examples/multiple_simple_compression.c @@ -26,9 +26,9 @@ typedef struct { /* * allocate memory for buffers big enough to compress all files - * as well as memory for output file name (outFilename) + * as well as memory for output file name (ofn) */ -static resources createResources_orDie(int argc, const char** argv, char **outFilename) +static resources createResources_orDie(int argc, const char** argv, char **ofn, int* ofnBufferLen) { size_t maxFilenameLength=0; size_t maxFileSize = 0; @@ -47,7 +47,8 @@ static resources createResources_orDie(int argc, const char** argv, char **outFi ress.fBufferSize = maxFileSize; ress.cBufferSize = ZSTD_compressBound(maxFileSize); - *outFilename = (char*)malloc_orDie(maxFilenameLength + 5); + *ofnBufferLen = maxFilenameLength + 5; + *ofn = (char*)malloc_orDie(*ofnBufferLen); ress.fBuffer = malloc_orDie(ress.fBufferSize); ress.cBuffer = malloc_orDie(ress.cBufferSize); ress.cctx = ZSTD_createCCtx(); @@ -66,8 +67,7 @@ static void freeResources(resources ress, char *outFilename) /* compress with pre-allocated context (ZSTD_CCtx) and input/output buffers*/ static void compressFile_orDie(resources ress, const char* fname, const char* oname) { - size_t fSize; - loadFile_orDie(fname, &fSize, ress.fBuffer, ress.fBufferSize); + size_t fSize = loadFile_orDie(fname, ress.fBuffer, ress.fBufferSize); size_t const cSize = ZSTD_compressCCtx(ress.cctx, ress.cBuffer, ress.cBufferSize, ress.fBuffer, fSize, 1); if (ZSTD_isError(cSize)) { @@ -94,15 +94,17 @@ int main(int argc, const char** argv) /* memory allocation for outFilename and resources */ char* outFilename; - resources ress = createResources_orDie(argc, argv, &outFilename); + int outFilenameBufferLen; + resources const ress = createResources_orDie(argc, argv, &outFilename, &outFilenameBufferLen); /* compress files with shared context, input and output buffers */ int argNb; for (argNb = 1; argNb < argc; argNb++) { const char* const inFilename = argv[argNb]; - memset(outFilename, 0, 1); - strcat(outFilename, inFilename); - strcat(outFilename, ".zst"); + int inFilenameLen = strlen(inFilename); + assert(inFilenameLen + 5 <= outFilenameBufferLen); + memcpy(outFilename, inFilename, inFilenameLen); + memcpy(outFilename+inFilenameLen, ".zst", 5); compressFile_orDie(ress, inFilename, outFilename); } diff --git a/examples/simple_compression.c b/examples/simple_compression.c index 7f1fa6cc6..829cbd7d8 100644 --- a/examples/simple_compression.c +++ b/examples/simple_compression.c @@ -19,7 +19,7 @@ static void compress_orDie(const char* fname, const char* oname) { size_t fSize; - void* const fBuff = loadFile_orDie(fname, &fSize, 0, 0); + void* const fBuff = mallocAndLoadFile_orDie(fname, &fSize); size_t const cBuffSize = ZSTD_compressBound(fSize); void* const cBuff = malloc_orDie(cBuffSize); diff --git a/examples/simple_decompression.c b/examples/simple_decompression.c index 00e020954..e7949376c 100644 --- a/examples/simple_decompression.c +++ b/examples/simple_decompression.c @@ -20,7 +20,7 @@ static void decompress(const char* fname) { size_t cSize; - void* const cBuff = loadFile_orDie(fname, &cSize, 0, 0); + void* const cBuff = mallocAndLoadFile_orDie(fname, &cSize); unsigned long long const rSize = ZSTD_findDecompressedSize(cBuff, cSize); if (rSize==ZSTD_CONTENTSIZE_ERROR) { fprintf(stderr, "%s : it was not compressed by zstd.\n", fname); diff --git a/examples/utils.h b/examples/utils.h index 7968d436f..6d1360457 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -18,6 +18,7 @@ #include // fprintf, perror, fopen, etc. #include // strlen, strcat, memset, strerror #include // errno +#include // assert #include // stat /* @@ -141,33 +142,43 @@ static void* malloc_orDie(size_t size) } /*! loadFile_orDie() : - * Read size bytes from a file. If buffer is not provided (i.e., buffer == null), - * malloc will be called to allocate one. + * load file into buffer (memory). * * Note: This function will send an error to stderr and exit if it * cannot read data from the given file path. * - * @return If successful this function will return a pointer to read - * data otherwise it will printout an error to stderr and exit. + * @return If successful this function will load file into buffer and + * return file size, otherwise it will printout an error to stderr and exit. */ -static void* loadFile_orDie(const char* fileName, size_t* size, void* buffer, int bufferSize) +static size_t loadFile_orDie(const char* fileName, void* buffer, int bufferSize) { size_t const fileSize = fsize_orDie(fileName); + assert(fileSize <= bufferSize); + FILE* const inFile = fopen_orDie(fileName, "rb"); - if (!buffer) { - buffer = malloc_orDie(fileSize); - } - else if (bufferSize < fileSize) { - fprintf(stderr, "%s : filesize bigger than provided buffer.\n", fileName); - exit(ERROR_largeFile); - } size_t const readSize = fread(buffer, 1, fileSize, inFile); if (readSize != (size_t)fileSize) { fprintf(stderr, "fread: %s : %s \n", fileName, strerror(errno)); exit(ERROR_fread); } fclose(inFile); /* can't fail, read only */ - *size = fileSize; + return fileSize; +} + +/*! mallocAndLoadFile_orDie() : + * allocate memory buffer and then load file into it. + * + * Note: This function will send an error to stderr and exit if memory allocation + * fails or it cannot read data from the given file path. + * + * @return If successful this function will return buffer and bufferSize(=fileSize), + * otherwise it will printout an error to stderr and exit. + */ +static void* mallocAndLoadFile_orDie(const char* fileName, size_t* bufferSize) { + size_t const fileSize = fsize_orDie(fileName); + *bufferSize = fileSize; + void* const buffer = malloc_orDie(*bufferSize); + loadFile_orDie(fileName, buffer, *bufferSize); return buffer; }