xref: /freebsd/sys/contrib/zstd/examples/common.h (revision 5ff13fbc199bdf5f0572845351c68ee5ca828e71)
12b9c00cbSConrad Meyer /*
2*5ff13fbcSAllan Jude  * Copyright (c) Yann Collet, Facebook, Inc.
32b9c00cbSConrad Meyer  * All rights reserved.
42b9c00cbSConrad Meyer  *
52b9c00cbSConrad Meyer  * This source code is licensed under both the BSD-style license (found in the
62b9c00cbSConrad Meyer  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
72b9c00cbSConrad Meyer  * in the COPYING file in the root directory of this source tree).
82b9c00cbSConrad Meyer  * You may select, at your option, one of the above-listed licenses.
92b9c00cbSConrad Meyer  */
102b9c00cbSConrad Meyer 
112b9c00cbSConrad Meyer /*
122b9c00cbSConrad Meyer  * This header file has common utility functions used in examples.
132b9c00cbSConrad Meyer  */
142b9c00cbSConrad Meyer #ifndef COMMON_H
152b9c00cbSConrad Meyer #define COMMON_H
162b9c00cbSConrad Meyer 
172b9c00cbSConrad Meyer #include <stdlib.h>    // malloc, free, exit
182b9c00cbSConrad Meyer #include <stdio.h>     // fprintf, perror, fopen, etc.
192b9c00cbSConrad Meyer #include <string.h>    // strerror
202b9c00cbSConrad Meyer #include <errno.h>     // errno
212b9c00cbSConrad Meyer #include <sys/stat.h>  // stat
222b9c00cbSConrad Meyer #include <zstd.h>
232b9c00cbSConrad Meyer 
242b9c00cbSConrad Meyer /*
252b9c00cbSConrad Meyer  * Define the returned error code from utility functions.
262b9c00cbSConrad Meyer  */
272b9c00cbSConrad Meyer typedef enum {
282b9c00cbSConrad Meyer     ERROR_fsize = 1,
292b9c00cbSConrad Meyer     ERROR_fopen = 2,
302b9c00cbSConrad Meyer     ERROR_fclose = 3,
312b9c00cbSConrad Meyer     ERROR_fread = 4,
322b9c00cbSConrad Meyer     ERROR_fwrite = 5,
332b9c00cbSConrad Meyer     ERROR_loadFile = 6,
342b9c00cbSConrad Meyer     ERROR_saveFile = 7,
352b9c00cbSConrad Meyer     ERROR_malloc = 8,
362b9c00cbSConrad Meyer     ERROR_largeFile = 9,
372b9c00cbSConrad Meyer } COMMON_ErrorCode;
382b9c00cbSConrad Meyer 
392b9c00cbSConrad Meyer /*! CHECK
402b9c00cbSConrad Meyer  * Check that the condition holds. If it doesn't print a message and die.
412b9c00cbSConrad Meyer  */
422b9c00cbSConrad Meyer #define CHECK(cond, ...)                        \
432b9c00cbSConrad Meyer     do {                                        \
442b9c00cbSConrad Meyer         if (!(cond)) {                          \
452b9c00cbSConrad Meyer             fprintf(stderr,                     \
462b9c00cbSConrad Meyer                     "%s:%d CHECK(%s) failed: ", \
472b9c00cbSConrad Meyer                     __FILE__,                   \
482b9c00cbSConrad Meyer                     __LINE__,                   \
492b9c00cbSConrad Meyer                     #cond);                     \
502b9c00cbSConrad Meyer             fprintf(stderr, "" __VA_ARGS__);    \
512b9c00cbSConrad Meyer             fprintf(stderr, "\n");              \
522b9c00cbSConrad Meyer             exit(1);                            \
532b9c00cbSConrad Meyer         }                                       \
542b9c00cbSConrad Meyer     } while (0)
552b9c00cbSConrad Meyer 
562b9c00cbSConrad Meyer /*! CHECK_ZSTD
572b9c00cbSConrad Meyer  * Check the zstd error code and die if an error occurred after printing a
582b9c00cbSConrad Meyer  * message.
592b9c00cbSConrad Meyer  */
60*5ff13fbcSAllan Jude #define CHECK_ZSTD(fn)                                           \
612b9c00cbSConrad Meyer     do {                                                         \
622b9c00cbSConrad Meyer         size_t const err = (fn);                                 \
632b9c00cbSConrad Meyer         CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
642b9c00cbSConrad Meyer     } while (0)
652b9c00cbSConrad Meyer 
662b9c00cbSConrad Meyer /*! fsize_orDie() :
672b9c00cbSConrad Meyer  * Get the size of a given file path.
682b9c00cbSConrad Meyer  *
692b9c00cbSConrad Meyer  * @return The size of a given file path.
702b9c00cbSConrad Meyer  */
fsize_orDie(const char * filename)712b9c00cbSConrad Meyer static size_t fsize_orDie(const char *filename)
722b9c00cbSConrad Meyer {
732b9c00cbSConrad Meyer     struct stat st;
742b9c00cbSConrad Meyer     if (stat(filename, &st) != 0) {
752b9c00cbSConrad Meyer         /* error */
762b9c00cbSConrad Meyer         perror(filename);
772b9c00cbSConrad Meyer         exit(ERROR_fsize);
782b9c00cbSConrad Meyer     }
792b9c00cbSConrad Meyer 
802b9c00cbSConrad Meyer     off_t const fileSize = st.st_size;
812b9c00cbSConrad Meyer     size_t const size = (size_t)fileSize;
822b9c00cbSConrad Meyer     /* 1. fileSize should be non-negative,
832b9c00cbSConrad Meyer      * 2. if off_t -> size_t type conversion results in discrepancy,
842b9c00cbSConrad Meyer      *    the file size is too large for type size_t.
852b9c00cbSConrad Meyer      */
862b9c00cbSConrad Meyer     if ((fileSize < 0) || (fileSize != (off_t)size)) {
872b9c00cbSConrad Meyer         fprintf(stderr, "%s : filesize too large \n", filename);
882b9c00cbSConrad Meyer         exit(ERROR_largeFile);
892b9c00cbSConrad Meyer     }
902b9c00cbSConrad Meyer     return size;
912b9c00cbSConrad Meyer }
922b9c00cbSConrad Meyer 
932b9c00cbSConrad Meyer /*! fopen_orDie() :
942b9c00cbSConrad Meyer  * Open a file using given file path and open option.
952b9c00cbSConrad Meyer  *
962b9c00cbSConrad Meyer  * @return If successful this function will return a FILE pointer to an
972b9c00cbSConrad Meyer  * opened file otherwise it sends an error to stderr and exits.
982b9c00cbSConrad Meyer  */
fopen_orDie(const char * filename,const char * instruction)992b9c00cbSConrad Meyer static FILE* fopen_orDie(const char *filename, const char *instruction)
1002b9c00cbSConrad Meyer {
1012b9c00cbSConrad Meyer     FILE* const inFile = fopen(filename, instruction);
1022b9c00cbSConrad Meyer     if (inFile) return inFile;
1032b9c00cbSConrad Meyer     /* error */
1042b9c00cbSConrad Meyer     perror(filename);
1052b9c00cbSConrad Meyer     exit(ERROR_fopen);
1062b9c00cbSConrad Meyer }
1072b9c00cbSConrad Meyer 
1082b9c00cbSConrad Meyer /*! fclose_orDie() :
1092b9c00cbSConrad Meyer  * Close an opened file using given FILE pointer.
1102b9c00cbSConrad Meyer  */
fclose_orDie(FILE * file)1112b9c00cbSConrad Meyer static void fclose_orDie(FILE* file)
1122b9c00cbSConrad Meyer {
1132b9c00cbSConrad Meyer     if (!fclose(file)) { return; };
1142b9c00cbSConrad Meyer     /* error */
1152b9c00cbSConrad Meyer     perror("fclose");
1162b9c00cbSConrad Meyer     exit(ERROR_fclose);
1172b9c00cbSConrad Meyer }
1182b9c00cbSConrad Meyer 
1192b9c00cbSConrad Meyer /*! fread_orDie() :
1202b9c00cbSConrad Meyer  *
1212b9c00cbSConrad Meyer  * Read sizeToRead bytes from a given file, storing them at the
1222b9c00cbSConrad Meyer  * location given by buffer.
1232b9c00cbSConrad Meyer  *
1242b9c00cbSConrad Meyer  * @return The number of bytes read.
1252b9c00cbSConrad Meyer  */
fread_orDie(void * buffer,size_t sizeToRead,FILE * file)1262b9c00cbSConrad Meyer static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)
1272b9c00cbSConrad Meyer {
1282b9c00cbSConrad Meyer     size_t const readSize = fread(buffer, 1, sizeToRead, file);
1292b9c00cbSConrad Meyer     if (readSize == sizeToRead) return readSize;   /* good */
1302b9c00cbSConrad Meyer     if (feof(file)) return readSize;   /* good, reached end of file */
1312b9c00cbSConrad Meyer     /* error */
1322b9c00cbSConrad Meyer     perror("fread");
1332b9c00cbSConrad Meyer     exit(ERROR_fread);
1342b9c00cbSConrad Meyer }
1352b9c00cbSConrad Meyer 
1362b9c00cbSConrad Meyer /*! fwrite_orDie() :
1372b9c00cbSConrad Meyer  *
1382b9c00cbSConrad Meyer  * Write sizeToWrite bytes to a file pointed to by file, obtaining
1392b9c00cbSConrad Meyer  * them from a location given by buffer.
1402b9c00cbSConrad Meyer  *
1412b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
1422b9c00cbSConrad Meyer  * cannot write data to the given file pointer.
1432b9c00cbSConrad Meyer  *
1442b9c00cbSConrad Meyer  * @return The number of bytes written.
1452b9c00cbSConrad Meyer  */
fwrite_orDie(const void * buffer,size_t sizeToWrite,FILE * file)1462b9c00cbSConrad Meyer static size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)
1472b9c00cbSConrad Meyer {
1482b9c00cbSConrad Meyer     size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);
1492b9c00cbSConrad Meyer     if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */
1502b9c00cbSConrad Meyer     /* error */
1512b9c00cbSConrad Meyer     perror("fwrite");
1522b9c00cbSConrad Meyer     exit(ERROR_fwrite);
1532b9c00cbSConrad Meyer }
1542b9c00cbSConrad Meyer 
1552b9c00cbSConrad Meyer /*! malloc_orDie() :
1562b9c00cbSConrad Meyer  * Allocate memory.
1572b9c00cbSConrad Meyer  *
1582b9c00cbSConrad Meyer  * @return If successful this function returns a pointer to allo-
1592b9c00cbSConrad Meyer  * cated memory.  If there is an error, this function will send that
1602b9c00cbSConrad Meyer  * error to stderr and exit.
1612b9c00cbSConrad Meyer  */
malloc_orDie(size_t size)1622b9c00cbSConrad Meyer static void* malloc_orDie(size_t size)
1632b9c00cbSConrad Meyer {
1642b9c00cbSConrad Meyer     void* const buff = malloc(size);
1652b9c00cbSConrad Meyer     if (buff) return buff;
1662b9c00cbSConrad Meyer     /* error */
1672b9c00cbSConrad Meyer     perror("malloc");
1682b9c00cbSConrad Meyer     exit(ERROR_malloc);
1692b9c00cbSConrad Meyer }
1702b9c00cbSConrad Meyer 
1712b9c00cbSConrad Meyer /*! loadFile_orDie() :
1722b9c00cbSConrad Meyer  * load file into buffer (memory).
1732b9c00cbSConrad Meyer  *
1742b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
1752b9c00cbSConrad Meyer  * cannot read data from the given file path.
1762b9c00cbSConrad Meyer  *
1772b9c00cbSConrad Meyer  * @return If successful this function will load file into buffer and
1782b9c00cbSConrad Meyer  * return file size, otherwise it will printout an error to stderr and exit.
1792b9c00cbSConrad Meyer  */
loadFile_orDie(const char * fileName,void * buffer,size_t bufferSize)1802b9c00cbSConrad Meyer static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
1812b9c00cbSConrad Meyer {
1822b9c00cbSConrad Meyer     size_t const fileSize = fsize_orDie(fileName);
1832b9c00cbSConrad Meyer     CHECK(fileSize <= bufferSize, "File too large!");
1842b9c00cbSConrad Meyer 
1852b9c00cbSConrad Meyer     FILE* const inFile = fopen_orDie(fileName, "rb");
1862b9c00cbSConrad Meyer     size_t const readSize = fread(buffer, 1, fileSize, inFile);
1872b9c00cbSConrad Meyer     if (readSize != (size_t)fileSize) {
1882b9c00cbSConrad Meyer         fprintf(stderr, "fread: %s : %s \n", fileName, strerror(errno));
1892b9c00cbSConrad Meyer         exit(ERROR_fread);
1902b9c00cbSConrad Meyer     }
1912b9c00cbSConrad Meyer     fclose(inFile);  /* can't fail, read only */
1922b9c00cbSConrad Meyer     return fileSize;
1932b9c00cbSConrad Meyer }
1942b9c00cbSConrad Meyer 
1952b9c00cbSConrad Meyer /*! mallocAndLoadFile_orDie() :
1962b9c00cbSConrad Meyer  * allocate memory buffer and then load file into it.
1972b9c00cbSConrad Meyer  *
1982b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if memory allocation
1992b9c00cbSConrad Meyer  * fails or it cannot read data from the given file path.
2002b9c00cbSConrad Meyer  *
2012b9c00cbSConrad Meyer  * @return If successful this function will return buffer and bufferSize(=fileSize),
2022b9c00cbSConrad Meyer  * otherwise it will printout an error to stderr and exit.
2032b9c00cbSConrad Meyer  */
mallocAndLoadFile_orDie(const char * fileName,size_t * bufferSize)2042b9c00cbSConrad Meyer static void* mallocAndLoadFile_orDie(const char* fileName, size_t* bufferSize) {
2052b9c00cbSConrad Meyer     size_t const fileSize = fsize_orDie(fileName);
2062b9c00cbSConrad Meyer     *bufferSize = fileSize;
2072b9c00cbSConrad Meyer     void* const buffer = malloc_orDie(*bufferSize);
2082b9c00cbSConrad Meyer     loadFile_orDie(fileName, buffer, *bufferSize);
2092b9c00cbSConrad Meyer     return buffer;
2102b9c00cbSConrad Meyer }
2112b9c00cbSConrad Meyer 
2122b9c00cbSConrad Meyer /*! saveFile_orDie() :
2132b9c00cbSConrad Meyer  *
2142b9c00cbSConrad Meyer  * Save buffSize bytes to a given file path, obtaining them from a location pointed
2152b9c00cbSConrad Meyer  * to by buff.
2162b9c00cbSConrad Meyer  *
2172b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
2182b9c00cbSConrad Meyer  * cannot write to a given file.
2192b9c00cbSConrad Meyer  */
saveFile_orDie(const char * fileName,const void * buff,size_t buffSize)2202b9c00cbSConrad Meyer static void saveFile_orDie(const char* fileName, const void* buff, size_t buffSize)
2212b9c00cbSConrad Meyer {
2222b9c00cbSConrad Meyer     FILE* const oFile = fopen_orDie(fileName, "wb");
2232b9c00cbSConrad Meyer     size_t const wSize = fwrite(buff, 1, buffSize, oFile);
2242b9c00cbSConrad Meyer     if (wSize != (size_t)buffSize) {
2252b9c00cbSConrad Meyer         fprintf(stderr, "fwrite: %s : %s \n", fileName, strerror(errno));
2262b9c00cbSConrad Meyer         exit(ERROR_fwrite);
2272b9c00cbSConrad Meyer     }
2282b9c00cbSConrad Meyer     if (fclose(oFile)) {
2292b9c00cbSConrad Meyer         perror(fileName);
2302b9c00cbSConrad Meyer         exit(ERROR_fclose);
2312b9c00cbSConrad Meyer     }
2322b9c00cbSConrad Meyer }
2332b9c00cbSConrad Meyer 
2342b9c00cbSConrad Meyer #endif
235