common.h 7.0 KB

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