FileSystem.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "Base.h"
  2. #include "FileSystem.h"
  3. #ifdef WIN32
  4. #include <windows.h>
  5. #include <tchar.h>
  6. #include <stdio.h>
  7. #else
  8. #include <dirent.h>
  9. #include <sys/stat.h>
  10. #endif
  11. #ifdef __ANDROID__
  12. extern AAssetManager* __assetManager;
  13. #endif
  14. namespace gameplay
  15. {
  16. #ifdef __ANDROID__
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <unistd.h>
  20. void makepath(std::string path, int mode)
  21. {
  22. std::vector<std::string> dirs;
  23. while (path.length() > 0)
  24. {
  25. int index = path.find('/');
  26. std::string dir = (index == -1 ) ? path : path.substr(0, index);
  27. if (dir.length() > 0)
  28. dirs.push_back(dir);
  29. if (index + 1 >= path.length() || index == -1)
  30. break;
  31. path = path.substr(index + 1);
  32. }
  33. struct stat s;
  34. std::string dirPath;
  35. for (unsigned int i = 0; i < dirs.size(); i++)
  36. {
  37. dirPath += "/";
  38. dirPath += dirs[i];
  39. if (stat(dirPath.c_str(), &s) != 0)
  40. {
  41. // Directory does not exist.
  42. if (mkdir(dirPath.c_str(), 0777) != 0)
  43. {
  44. WARN_VARG("Failed to create directory: '%s'", dirPath.c_str());
  45. return;
  46. }
  47. }
  48. }
  49. return;
  50. }
  51. #endif
  52. static std::string __resourcePath("./");
  53. FileSystem::FileSystem()
  54. {
  55. }
  56. FileSystem::~FileSystem()
  57. {
  58. }
  59. void FileSystem::setResourcePath(const char* path)
  60. {
  61. __resourcePath = path == NULL ? "" : path;
  62. }
  63. const char* FileSystem::getResourcePath()
  64. {
  65. return __resourcePath.c_str();
  66. }
  67. bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
  68. {
  69. // TODO make this method work with absolute and relative paths.
  70. #ifdef WIN32
  71. std::string path(FileSystem::getResourcePath());
  72. if (dirPath && strlen(dirPath) > 0)
  73. {
  74. path.append(dirPath);
  75. }
  76. path.append("/*");
  77. // Convert char to wchar
  78. std::basic_string<TCHAR> wPath;
  79. wPath.assign(path.begin(), path.end());
  80. WIN32_FIND_DATA FindFileData;
  81. HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData);
  82. if (hFind == INVALID_HANDLE_VALUE)
  83. {
  84. return false;
  85. }
  86. do
  87. {
  88. // Add to the list if this is not a directory
  89. if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  90. {
  91. // Convert wchar to char
  92. std::basic_string<TCHAR> wfilename(FindFileData.cFileName);
  93. std::string filename;
  94. filename.assign(wfilename.begin(), wfilename.end());
  95. files.push_back(filename);
  96. }
  97. } while (FindNextFile(hFind, &FindFileData) != 0);
  98. FindClose(hFind);
  99. return true;
  100. #else
  101. std::string path(FileSystem::getResourcePath());
  102. if (dirPath && strlen(dirPath) > 0)
  103. {
  104. path.append(dirPath);
  105. }
  106. path.append("/.");
  107. struct dirent* dp;
  108. DIR* dir = opendir(path.c_str());
  109. if (!dir)
  110. {
  111. return false;
  112. }
  113. while ((dp = readdir(dir)) != NULL)
  114. {
  115. std::string filepath(path);
  116. filepath.append("/");
  117. filepath.append(dp->d_name);
  118. struct stat buf;
  119. if (!stat(filepath.c_str(), &buf))
  120. {
  121. // Add to the list if this is not a directory
  122. if (!S_ISDIR(buf.st_mode))
  123. {
  124. files.push_back(dp->d_name);
  125. }
  126. }
  127. }
  128. closedir(dir);
  129. return true;
  130. #endif
  131. }
  132. FILE* FileSystem::openFile(const char* path, const char* mode)
  133. {
  134. std::string fullPath(__resourcePath);
  135. fullPath += path;
  136. #ifdef __ANDROID__
  137. std::string directoryPath = fullPath.substr(0, fullPath.rfind('/'));
  138. struct stat s;
  139. if (stat(directoryPath.c_str(), &s) != 0)
  140. makepath(directoryPath.c_str(), 0777);
  141. if (stat(fullPath.c_str(), &s) != 0)
  142. {
  143. AAsset* asset = AAssetManager_open(__assetManager, path, AASSET_MODE_RANDOM);
  144. if (asset)
  145. {
  146. const void* data = AAsset_getBuffer(asset);
  147. int length = AAsset_getLength(asset);
  148. FILE* file = fopen(fullPath.c_str(), "wb");
  149. int ret = fwrite(data, sizeof(unsigned char), length, file);
  150. assert(ret == length);
  151. fclose(file);
  152. }
  153. }
  154. #endif
  155. FILE* fp = fopen(fullPath.c_str(), mode);
  156. // Win32 doesn't support an asset or bundle definitions.
  157. #ifdef WIN32
  158. if (fp == NULL)
  159. {
  160. fullPath = __resourcePath;
  161. fullPath += "../../gameplay/";
  162. fullPath += path;
  163. fp = fopen(fullPath.c_str(), mode);
  164. }
  165. #endif
  166. return fp;
  167. }
  168. char* FileSystem::readAll(const char* filePath, int* fileSize)
  169. {
  170. // Open file for reading.
  171. FILE* file = openFile(filePath, "rb");
  172. if (file == NULL)
  173. {
  174. LOG_ERROR_VARG("Failed to load file: %s", filePath);
  175. return NULL;
  176. }
  177. // Obtain file length.
  178. fseek(file, 0, SEEK_END);
  179. int size = (int)ftell(file);
  180. fseek(file, 0, SEEK_SET);
  181. // Read entire file contents.
  182. char* buffer = new char[size + 1];
  183. int read = (int)fread(buffer, 1, size, file);
  184. assert(read == size);
  185. if (read != size)
  186. {
  187. LOG_ERROR_VARG("Read error for file: %s (%d < %d)", filePath, (int)read, (int)size);
  188. SAFE_DELETE_ARRAY(buffer);
  189. return NULL;
  190. }
  191. // Force the character buffer to be NULL-terminated.
  192. buffer[size] = '\0';
  193. // Close file and return.
  194. fclose(file);
  195. if (fileSize)
  196. {
  197. *fileSize = size;
  198. }
  199. return buffer;
  200. }
  201. }