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