FileSystem.cpp 5.6 KB

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