A collection of basic/generally desirable code I use across multiple C++ projects.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
4.8 KiB

1 year ago
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h> // fopen, fseek, ftell, fclose
  3. #undef _CRT_SECURE_NO_WARNINGS
  4. #include "alloc.h"
  5. #include "array.hpp"
  6. #include "file.h"
  7. #include "print.h"
  8. #include "types.h"
  9. FILE* File::Open(const char* path, const char* mode) {
  10. TYPES_H_FTAG;
  11. return fopen(path, mode);
  12. }
  13. FILE* File::Open(const char* path, size_t* outSize, const char* mode) {
  14. TYPES_H_FTAG;
  15. FILE* fp = File::Open(path, mode);
  16. if (fp == null) {
  17. return null;
  18. }
  19. // get the file's size in bytes
  20. fseek(fp, 0, SEEK_END);
  21. *outSize = ftell(fp);
  22. fseek(fp, 0L, SEEK_SET);
  23. return fp;
  24. }
  25. void File::Close(FILE* file) {
  26. fclose(file);
  27. }
  28. size_t File::Size(const char* path) {
  29. TYPES_H_FTAG;
  30. FILE* fp = File::Open(path);
  31. // get the file's size in bytes
  32. fseek(fp, 0, SEEK_END);
  33. size_t size = ftell(fp);
  34. fseek(fp, 0L, SEEK_SET);
  35. fclose(fp);
  36. return size;
  37. }
  38. size_t File::Size(FILE* fp) {
  39. TYPES_H_FTAG;
  40. fseek(fp, 0, SEEK_END);
  41. size_t size = ftell(fp);
  42. fseek(fp, 0L, SEEK_SET);
  43. return size;
  44. }
  45. u8* File::Read(const char* path) {
  46. TYPES_H_FTAG;
  47. FILE* fp = File::Open(path, "rb");
  48. if (fp == null) {
  49. return null;
  50. }
  51. // get the file's size in bytes
  52. fseek(fp, 0, SEEK_END);
  53. u32 size = ftell(fp);
  54. fseek(fp, 0L, SEEK_SET);
  55. char* buffer = (char*) pMalloc(size + 1);
  56. fread(buffer, sizeof (char), size + 1, fp);
  57. buffer[size] = '\0';
  58. fclose(fp);
  59. return (u8*) buffer;
  60. }
  61. u8* File::Read(const char* path, size_t* outSize) {
  62. TYPES_H_FTAG;
  63. FILE* fp = File::Open(path, "rb");
  64. if (fp == null) {
  65. return null;
  66. }
  67. // get the file's size in bytes
  68. fseek(fp, 0, SEEK_END);
  69. size_t size = ftell(fp);
  70. // if we got a valid pointer to a size_t we should report the size back.
  71. if (outSize != null) {
  72. *outSize = size;
  73. }
  74. fseek(fp, 0L, SEEK_SET);
  75. char* buffer = (char*) pMalloc(size + 1);
  76. fread(buffer, sizeof (char), size + 1, fp);
  77. buffer[size] = '\0';
  78. fclose(fp);
  79. return (u8*) buffer;
  80. }
  81. size_t File::Read(FILE* fp, void* destination) {
  82. TYPES_H_FTAG;
  83. fseek(fp, 0, SEEK_END);
  84. size_t size = ftell(fp);
  85. fseek(fp, 0L, SEEK_SET);
  86. fread(destination, sizeof (char), size + 1, fp);
  87. return size;
  88. }
  89. size_t File::Read(FILE* fp, void* destination, size_t size) {
  90. TYPES_H_FTAG;
  91. return fread(destination, sizeof (char), size + 1, fp);
  92. }
  93. s32 File::Write(const char* path, char* data, u32 count) {
  94. TYPES_H_FTAG;
  95. FILE* fp = File::Open(path, "wb");
  96. if (fp == null) {
  97. return -1; // failed to open the file
  98. }
  99. size_t writtenCount = fwrite(data, 1, count, fp);
  100. fclose(fp);
  101. if (writtenCount != count) {
  102. return -2; // wrote only partially
  103. }
  104. return 0;
  105. }
  106. #if _WIN32
  107. #include <windows.h>
  108. // writes the filenames into the provided array |outFileNames|, must be allocated ahead of time.
  109. void File::GetFileNamesInFolder(const char* path, Array<char*>* outFileNames) {
  110. TYPES_H_FTAG;
  111. massert(path != null, "provided 'null' for path argument");
  112. massert(outFileNames != null, "provided 'null' for array argument");
  113. WIN32_FIND_DATAA findData;
  114. HANDLE hFind = INVALID_HANDLE_VALUE;
  115. String str;
  116. if (path[String::len(path) - 1] != '/') {
  117. str = String64f("%s/*", path);
  118. } else {
  119. str = String64f("%s*", path);
  120. }
  121. hFind = FindFirstFileA(str.c_str(), &findData);
  122. if (hFind == INVALID_HANDLE_VALUE) die("failed to open folder: %s", path);
  123. while (FindNextFileA(hFind, &findData) != 0) {
  124. if (findData.cFileName[0] != '.') {
  125. outFileNames->push(String::cpy(findData.cFileName));
  126. }
  127. }
  128. FindClose(hFind);
  129. }
  130. #else
  131. #include <dirent.h>
  132. void File::GetFileNamesInFolder(const char* path, Array<char*>* outFileNames) {
  133. TYPES_H_FTAG;
  134. massert(path != null, "provided 'null' for path argument");
  135. massert(outFileNames != null, "provided 'null' for array argument");
  136. DIR* dir = opendir(path);
  137. struct dirent* d;
  138. if (dir == null) die("failed to open folder: %s", path);
  139. do {
  140. d = readdir(dir);
  141. if (d == null) break;
  142. if (d->d_name[0] != '.') outFileNames->push(String::cpy(d->d_name));
  143. } while (1);
  144. closedir(dir);
  145. }
  146. #endif
  147. #include <sys/types.h>
  148. #include <sys/stat.h>
  149. #ifndef WIN32
  150. #include <unistd.h>
  151. #endif
  152. // msvc provides a 'stat' equivalent as _stat.
  153. #ifdef WIN32
  154. #define stat _stat
  155. #endif
  156. time_t File::LastModified(const char* path) {
  157. TYPES_H_FTAG;
  158. struct stat result;
  159. if (stat(path, &result) == 0) {
  160. return result.st_mtime;
  161. }
  162. massert(false, "failed to get last modified timestamp.");
  163. return -1;
  164. }
  165. #undef stat
  166. s32 File::Rename(const char* oldFilename, const char* newFilename) {
  167. return rename(oldFilename, newFilename);
  168. }
  169. s32 File::Remove(const char* path) {
  170. return remove(path);
  171. }