xref: /freebsd/sys/contrib/zstd/examples/common.h (revision 2b9c00cb6bd9392645dc8afca59cf57c42df4e2d)
1*2b9c00cbSConrad Meyer /*
2*2b9c00cbSConrad Meyer  * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3*2b9c00cbSConrad Meyer  * All rights reserved.
4*2b9c00cbSConrad Meyer  *
5*2b9c00cbSConrad Meyer  * This source code is licensed under both the BSD-style license (found in the
6*2b9c00cbSConrad Meyer  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*2b9c00cbSConrad Meyer  * in the COPYING file in the root directory of this source tree).
8*2b9c00cbSConrad Meyer  * You may select, at your option, one of the above-listed licenses.
9*2b9c00cbSConrad Meyer  */
10*2b9c00cbSConrad Meyer 
11*2b9c00cbSConrad Meyer /*
12*2b9c00cbSConrad Meyer  * This header file has common utility functions used in examples.
13*2b9c00cbSConrad Meyer  */
14*2b9c00cbSConrad Meyer #ifndef COMMON_H
15*2b9c00cbSConrad Meyer #define COMMON_H
16*2b9c00cbSConrad Meyer 
17*2b9c00cbSConrad Meyer #include <stdlib.h>    // malloc, free, exit
18*2b9c00cbSConrad Meyer #include <stdio.h>     // fprintf, perror, fopen, etc.
19*2b9c00cbSConrad Meyer #include <string.h>    // strerror
20*2b9c00cbSConrad Meyer #include <errno.h>     // errno
21*2b9c00cbSConrad Meyer #include <sys/stat.h>  // stat
22*2b9c00cbSConrad Meyer #include <zstd.h>
23*2b9c00cbSConrad Meyer 
24*2b9c00cbSConrad Meyer /*
25*2b9c00cbSConrad Meyer  * Define the returned error code from utility functions.
26*2b9c00cbSConrad Meyer  */
27*2b9c00cbSConrad Meyer typedef enum {
28*2b9c00cbSConrad Meyer     ERROR_fsize = 1,
29*2b9c00cbSConrad Meyer     ERROR_fopen = 2,
30*2b9c00cbSConrad Meyer     ERROR_fclose = 3,
31*2b9c00cbSConrad Meyer     ERROR_fread = 4,
32*2b9c00cbSConrad Meyer     ERROR_fwrite = 5,
33*2b9c00cbSConrad Meyer     ERROR_loadFile = 6,
34*2b9c00cbSConrad Meyer     ERROR_saveFile = 7,
35*2b9c00cbSConrad Meyer     ERROR_malloc = 8,
36*2b9c00cbSConrad Meyer     ERROR_largeFile = 9,
37*2b9c00cbSConrad Meyer } COMMON_ErrorCode;
38*2b9c00cbSConrad Meyer 
39*2b9c00cbSConrad Meyer /*! CHECK
40*2b9c00cbSConrad Meyer  * Check that the condition holds. If it doesn't print a message and die.
41*2b9c00cbSConrad Meyer  */
42*2b9c00cbSConrad Meyer #define CHECK(cond, ...)                        \
43*2b9c00cbSConrad Meyer     do {                                        \
44*2b9c00cbSConrad Meyer         if (!(cond)) {                          \
45*2b9c00cbSConrad Meyer             fprintf(stderr,                     \
46*2b9c00cbSConrad Meyer                     "%s:%d CHECK(%s) failed: ", \
47*2b9c00cbSConrad Meyer                     __FILE__,                   \
48*2b9c00cbSConrad Meyer                     __LINE__,                   \
49*2b9c00cbSConrad Meyer                     #cond);                     \
50*2b9c00cbSConrad Meyer             fprintf(stderr, "" __VA_ARGS__);    \
51*2b9c00cbSConrad Meyer             fprintf(stderr, "\n");              \
52*2b9c00cbSConrad Meyer             exit(1);                            \
53*2b9c00cbSConrad Meyer         }                                       \
54*2b9c00cbSConrad Meyer     } while (0)
55*2b9c00cbSConrad Meyer 
56*2b9c00cbSConrad Meyer /*! CHECK_ZSTD
57*2b9c00cbSConrad Meyer  * Check the zstd error code and die if an error occurred after printing a
58*2b9c00cbSConrad Meyer  * message.
59*2b9c00cbSConrad Meyer  */
60*2b9c00cbSConrad Meyer #define CHECK_ZSTD(fn, ...)                                      \
61*2b9c00cbSConrad Meyer     do {                                                         \
62*2b9c00cbSConrad Meyer         size_t const err = (fn);                                 \
63*2b9c00cbSConrad Meyer         CHECK(!ZSTD_isError(err), "%s", ZSTD_getErrorName(err)); \
64*2b9c00cbSConrad Meyer     } while (0)
65*2b9c00cbSConrad Meyer 
66*2b9c00cbSConrad Meyer /*! fsize_orDie() :
67*2b9c00cbSConrad Meyer  * Get the size of a given file path.
68*2b9c00cbSConrad Meyer  *
69*2b9c00cbSConrad Meyer  * @return The size of a given file path.
70*2b9c00cbSConrad Meyer  */
71*2b9c00cbSConrad Meyer static size_t fsize_orDie(const char *filename)
72*2b9c00cbSConrad Meyer {
73*2b9c00cbSConrad Meyer     struct stat st;
74*2b9c00cbSConrad Meyer     if (stat(filename, &st) != 0) {
75*2b9c00cbSConrad Meyer         /* error */
76*2b9c00cbSConrad Meyer         perror(filename);
77*2b9c00cbSConrad Meyer         exit(ERROR_fsize);
78*2b9c00cbSConrad Meyer     }
79*2b9c00cbSConrad Meyer 
80*2b9c00cbSConrad Meyer     off_t const fileSize = st.st_size;
81*2b9c00cbSConrad Meyer     size_t const size = (size_t)fileSize;
82*2b9c00cbSConrad Meyer     /* 1. fileSize should be non-negative,
83*2b9c00cbSConrad Meyer      * 2. if off_t -> size_t type conversion results in discrepancy,
84*2b9c00cbSConrad Meyer      *    the file size is too large for type size_t.
85*2b9c00cbSConrad Meyer      */
86*2b9c00cbSConrad Meyer     if ((fileSize < 0) || (fileSize != (off_t)size)) {
87*2b9c00cbSConrad Meyer         fprintf(stderr, "%s : filesize too large \n", filename);
88*2b9c00cbSConrad Meyer         exit(ERROR_largeFile);
89*2b9c00cbSConrad Meyer     }
90*2b9c00cbSConrad Meyer     return size;
91*2b9c00cbSConrad Meyer }
92*2b9c00cbSConrad Meyer 
93*2b9c00cbSConrad Meyer /*! fopen_orDie() :
94*2b9c00cbSConrad Meyer  * Open a file using given file path and open option.
95*2b9c00cbSConrad Meyer  *
96*2b9c00cbSConrad Meyer  * @return If successful this function will return a FILE pointer to an
97*2b9c00cbSConrad Meyer  * opened file otherwise it sends an error to stderr and exits.
98*2b9c00cbSConrad Meyer  */
99*2b9c00cbSConrad Meyer static FILE* fopen_orDie(const char *filename, const char *instruction)
100*2b9c00cbSConrad Meyer {
101*2b9c00cbSConrad Meyer     FILE* const inFile = fopen(filename, instruction);
102*2b9c00cbSConrad Meyer     if (inFile) return inFile;
103*2b9c00cbSConrad Meyer     /* error */
104*2b9c00cbSConrad Meyer     perror(filename);
105*2b9c00cbSConrad Meyer     exit(ERROR_fopen);
106*2b9c00cbSConrad Meyer }
107*2b9c00cbSConrad Meyer 
108*2b9c00cbSConrad Meyer /*! fclose_orDie() :
109*2b9c00cbSConrad Meyer  * Close an opened file using given FILE pointer.
110*2b9c00cbSConrad Meyer  */
111*2b9c00cbSConrad Meyer static void fclose_orDie(FILE* file)
112*2b9c00cbSConrad Meyer {
113*2b9c00cbSConrad Meyer     if (!fclose(file)) { return; };
114*2b9c00cbSConrad Meyer     /* error */
115*2b9c00cbSConrad Meyer     perror("fclose");
116*2b9c00cbSConrad Meyer     exit(ERROR_fclose);
117*2b9c00cbSConrad Meyer }
118*2b9c00cbSConrad Meyer 
119*2b9c00cbSConrad Meyer /*! fread_orDie() :
120*2b9c00cbSConrad Meyer  *
121*2b9c00cbSConrad Meyer  * Read sizeToRead bytes from a given file, storing them at the
122*2b9c00cbSConrad Meyer  * location given by buffer.
123*2b9c00cbSConrad Meyer  *
124*2b9c00cbSConrad Meyer  * @return The number of bytes read.
125*2b9c00cbSConrad Meyer  */
126*2b9c00cbSConrad Meyer static size_t fread_orDie(void* buffer, size_t sizeToRead, FILE* file)
127*2b9c00cbSConrad Meyer {
128*2b9c00cbSConrad Meyer     size_t const readSize = fread(buffer, 1, sizeToRead, file);
129*2b9c00cbSConrad Meyer     if (readSize == sizeToRead) return readSize;   /* good */
130*2b9c00cbSConrad Meyer     if (feof(file)) return readSize;   /* good, reached end of file */
131*2b9c00cbSConrad Meyer     /* error */
132*2b9c00cbSConrad Meyer     perror("fread");
133*2b9c00cbSConrad Meyer     exit(ERROR_fread);
134*2b9c00cbSConrad Meyer }
135*2b9c00cbSConrad Meyer 
136*2b9c00cbSConrad Meyer /*! fwrite_orDie() :
137*2b9c00cbSConrad Meyer  *
138*2b9c00cbSConrad Meyer  * Write sizeToWrite bytes to a file pointed to by file, obtaining
139*2b9c00cbSConrad Meyer  * them from a location given by buffer.
140*2b9c00cbSConrad Meyer  *
141*2b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
142*2b9c00cbSConrad Meyer  * cannot write data to the given file pointer.
143*2b9c00cbSConrad Meyer  *
144*2b9c00cbSConrad Meyer  * @return The number of bytes written.
145*2b9c00cbSConrad Meyer  */
146*2b9c00cbSConrad Meyer static size_t fwrite_orDie(const void* buffer, size_t sizeToWrite, FILE* file)
147*2b9c00cbSConrad Meyer {
148*2b9c00cbSConrad Meyer     size_t const writtenSize = fwrite(buffer, 1, sizeToWrite, file);
149*2b9c00cbSConrad Meyer     if (writtenSize == sizeToWrite) return sizeToWrite;   /* good */
150*2b9c00cbSConrad Meyer     /* error */
151*2b9c00cbSConrad Meyer     perror("fwrite");
152*2b9c00cbSConrad Meyer     exit(ERROR_fwrite);
153*2b9c00cbSConrad Meyer }
154*2b9c00cbSConrad Meyer 
155*2b9c00cbSConrad Meyer /*! malloc_orDie() :
156*2b9c00cbSConrad Meyer  * Allocate memory.
157*2b9c00cbSConrad Meyer  *
158*2b9c00cbSConrad Meyer  * @return If successful this function returns a pointer to allo-
159*2b9c00cbSConrad Meyer  * cated memory.  If there is an error, this function will send that
160*2b9c00cbSConrad Meyer  * error to stderr and exit.
161*2b9c00cbSConrad Meyer  */
162*2b9c00cbSConrad Meyer static void* malloc_orDie(size_t size)
163*2b9c00cbSConrad Meyer {
164*2b9c00cbSConrad Meyer     void* const buff = malloc(size);
165*2b9c00cbSConrad Meyer     if (buff) return buff;
166*2b9c00cbSConrad Meyer     /* error */
167*2b9c00cbSConrad Meyer     perror("malloc");
168*2b9c00cbSConrad Meyer     exit(ERROR_malloc);
169*2b9c00cbSConrad Meyer }
170*2b9c00cbSConrad Meyer 
171*2b9c00cbSConrad Meyer /*! loadFile_orDie() :
172*2b9c00cbSConrad Meyer  * load file into buffer (memory).
173*2b9c00cbSConrad Meyer  *
174*2b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
175*2b9c00cbSConrad Meyer  * cannot read data from the given file path.
176*2b9c00cbSConrad Meyer  *
177*2b9c00cbSConrad Meyer  * @return If successful this function will load file into buffer and
178*2b9c00cbSConrad Meyer  * return file size, otherwise it will printout an error to stderr and exit.
179*2b9c00cbSConrad Meyer  */
180*2b9c00cbSConrad Meyer static size_t loadFile_orDie(const char* fileName, void* buffer, size_t bufferSize)
181*2b9c00cbSConrad Meyer {
182*2b9c00cbSConrad Meyer     size_t const fileSize = fsize_orDie(fileName);
183*2b9c00cbSConrad Meyer     CHECK(fileSize <= bufferSize, "File too large!");
184*2b9c00cbSConrad Meyer 
185*2b9c00cbSConrad Meyer     FILE* const inFile = fopen_orDie(fileName, "rb");
186*2b9c00cbSConrad Meyer     size_t const readSize = fread(buffer, 1, fileSize, inFile);
187*2b9c00cbSConrad Meyer     if (readSize != (size_t)fileSize) {
188*2b9c00cbSConrad Meyer         fprintf(stderr, "fread: %s : %s \n", fileName, strerror(errno));
189*2b9c00cbSConrad Meyer         exit(ERROR_fread);
190*2b9c00cbSConrad Meyer     }
191*2b9c00cbSConrad Meyer     fclose(inFile);  /* can't fail, read only */
192*2b9c00cbSConrad Meyer     return fileSize;
193*2b9c00cbSConrad Meyer }
194*2b9c00cbSConrad Meyer 
195*2b9c00cbSConrad Meyer /*! mallocAndLoadFile_orDie() :
196*2b9c00cbSConrad Meyer  * allocate memory buffer and then load file into it.
197*2b9c00cbSConrad Meyer  *
198*2b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if memory allocation
199*2b9c00cbSConrad Meyer  * fails or it cannot read data from the given file path.
200*2b9c00cbSConrad Meyer  *
201*2b9c00cbSConrad Meyer  * @return If successful this function will return buffer and bufferSize(=fileSize),
202*2b9c00cbSConrad Meyer  * otherwise it will printout an error to stderr and exit.
203*2b9c00cbSConrad Meyer  */
204*2b9c00cbSConrad Meyer static void* mallocAndLoadFile_orDie(const char* fileName, size_t* bufferSize) {
205*2b9c00cbSConrad Meyer     size_t const fileSize = fsize_orDie(fileName);
206*2b9c00cbSConrad Meyer     *bufferSize = fileSize;
207*2b9c00cbSConrad Meyer     void* const buffer = malloc_orDie(*bufferSize);
208*2b9c00cbSConrad Meyer     loadFile_orDie(fileName, buffer, *bufferSize);
209*2b9c00cbSConrad Meyer     return buffer;
210*2b9c00cbSConrad Meyer }
211*2b9c00cbSConrad Meyer 
212*2b9c00cbSConrad Meyer /*! saveFile_orDie() :
213*2b9c00cbSConrad Meyer  *
214*2b9c00cbSConrad Meyer  * Save buffSize bytes to a given file path, obtaining them from a location pointed
215*2b9c00cbSConrad Meyer  * to by buff.
216*2b9c00cbSConrad Meyer  *
217*2b9c00cbSConrad Meyer  * Note: This function will send an error to stderr and exit if it
218*2b9c00cbSConrad Meyer  * cannot write to a given file.
219*2b9c00cbSConrad Meyer  */
220*2b9c00cbSConrad Meyer static void saveFile_orDie(const char* fileName, const void* buff, size_t buffSize)
221*2b9c00cbSConrad Meyer {
222*2b9c00cbSConrad Meyer     FILE* const oFile = fopen_orDie(fileName, "wb");
223*2b9c00cbSConrad Meyer     size_t const wSize = fwrite(buff, 1, buffSize, oFile);
224*2b9c00cbSConrad Meyer     if (wSize != (size_t)buffSize) {
225*2b9c00cbSConrad Meyer         fprintf(stderr, "fwrite: %s : %s \n", fileName, strerror(errno));
226*2b9c00cbSConrad Meyer         exit(ERROR_fwrite);
227*2b9c00cbSConrad Meyer     }
228*2b9c00cbSConrad Meyer     if (fclose(oFile)) {
229*2b9c00cbSConrad Meyer         perror(fileName);
230*2b9c00cbSConrad Meyer         exit(ERROR_fclose);
231*2b9c00cbSConrad Meyer     }
232*2b9c00cbSConrad Meyer }
233*2b9c00cbSConrad Meyer 
234*2b9c00cbSConrad Meyer #endif
235