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