Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Folder.cpp 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*!
  2. * \file src/utils/Folder.cpp
  3. * \brief Recursive file-system walking utilities
  4. *
  5. * \author xythobuz
  6. */
  7. #include <algorithm>
  8. #include <iostream>
  9. #include <sstream>
  10. #include "global.h"
  11. #include "utils/filesystem.h"
  12. #include "utils/File.h"
  13. #include "utils/Folder.h"
  14. #if defined(HAVE_DIRENT_H) && defined(HAVE_OPENDIR) && defined(HAVE_READDIR_R) && defined(HAVE_CLOSEDIR) && defined(HAVE_DT_DIR)
  15. #include <dirent.h>
  16. #define USE_DIRENT
  17. #elif defined (_WIN32)
  18. #include <windows.h>
  19. #define USE_FINDFILE
  20. #else
  21. #error No support for recursive folder traversal
  22. #endif
  23. Folder::Folder(std::string folder, bool listDotFiles) {
  24. if (((folder.length() == 0) || (folder.compare(".") == 0))
  25. #ifdef _WIN32
  26. || ((folder.compare(1, 2, std::string(":\\")) != 0) && (folder.at(0) != '~'))
  27. #else
  28. || ((folder.at(0) != '/') && (folder.at(0) != '~'))
  29. #endif
  30. ) {
  31. // Prepend current working directory
  32. path = getCurrentWorkingDirectory();
  33. if (folder.length() > 1)
  34. path += folder.substr(1);
  35. } else if (folder.at(0) == '~') {
  36. // Prepend home directory
  37. path = getHomeDirectory();
  38. std::cout << "Home: " << path << std::endl;
  39. if (folder.length() > 1)
  40. path += folder.substr(1);
  41. } else {
  42. path = folder;
  43. }
  44. // Find all '\\' replace with '/'
  45. size_t pos = path.find('\\');
  46. while (pos != std::string::npos) {
  47. path.at(pos) = '/';
  48. pos = path.find('\\');
  49. }
  50. size_t last = path.rfind('/', path.length() - 2);
  51. name = path.substr(last + 1);
  52. if (name.back() == '/')
  53. name.erase(name.length() - 1);
  54. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  55. if (path.back() != '/')
  56. path.append(1, '/');
  57. hasListed = false;
  58. listDot = listDotFiles;
  59. }
  60. std::string &Folder::getName() {
  61. return name;
  62. }
  63. std::string &Folder::getPath() {
  64. return path;
  65. }
  66. unsigned long Folder::fileCount() {
  67. createFolderItems();
  68. return files.size();
  69. }
  70. File &Folder::getFile(unsigned long i) {
  71. createFolderItems();
  72. assert(i < files.size());
  73. return files.at(i);
  74. }
  75. unsigned long Folder::folderCount() {
  76. createFolderItems();
  77. return folders.size();
  78. }
  79. Folder &Folder::getFolder(unsigned long i) {
  80. createFolderItems();
  81. assert(i < folders.size());
  82. return folders.at(i);
  83. }
  84. unsigned long Folder::countRecursiveItems() {
  85. unsigned long count = fileCount();
  86. for (unsigned long i = 0; i < folderCount(); i++)
  87. count += getFolder(i).countRecursiveItems();
  88. return count;
  89. }
  90. void Folder::executeRemoveRecursiveItems(std::function<bool (File &f)> func) {
  91. for (unsigned long i = 0; i < fileCount(); i++) {
  92. if (func(getFile(i))) {
  93. files.erase(files.begin() + (long)i--);
  94. }
  95. }
  96. for (unsigned long i = 0; i < folderCount(); i++) {
  97. getFolder(i).executeRemoveRecursiveItems(func);
  98. }
  99. }
  100. std::string Folder::getRecursiveItemName(unsigned long i) {
  101. assert(i < countRecursiveItems());
  102. if (i < fileCount()) {
  103. return getFile(i).getName();
  104. } else {
  105. unsigned long count = fileCount();
  106. for (unsigned long n = 0; n < folderCount(); n++) {
  107. if ((i - count) < getFolder(n).countRecursiveItems()) {
  108. return getFolder(n).getName() + '/'
  109. + getFolder(n).getRecursiveItemName(i - count);
  110. }
  111. count += getFolder(n).countRecursiveItems();
  112. }
  113. }
  114. assert(false);
  115. return "";
  116. }
  117. /*
  118. File &Folder::getRecursiveItem(unsigned long i) {
  119. assert(i < countRecursiveItems());
  120. if (i < fileCount()) {
  121. return getFile(i);
  122. } else {
  123. unsigned long count = fileCount();
  124. for (unsigned long n = 0; n < folderCount(); n++) {
  125. if ((i - count) < getFolder(n).countRecursiveItems()) {
  126. return getFolder(n).getRecursiveItem(i - count);
  127. }
  128. count += getFolder(n).countRecursiveItems();
  129. }
  130. }
  131. assert(false);
  132. return files.at(0);
  133. }
  134. */
  135. void Folder::createFolderItems() {
  136. if (hasListed)
  137. return;
  138. std::vector<std::string> foundFiles, foundFolders;
  139. if (readFolderItems(foundFiles, foundFolders) != 0)
  140. throw Exception(std::string("Could not open folder ") + name);
  141. if (!listDot) {
  142. std::vector<std::string>::iterator it = foundFiles.begin();
  143. while (it != foundFiles.end()) {
  144. size_t pos = it->rfind('/', it->length() - 2);
  145. if (it->at(pos + 1) == '.')
  146. it = foundFiles.erase(it);
  147. else
  148. ++it;
  149. }
  150. it = foundFolders.begin();
  151. while (it != foundFolders.end()) {
  152. size_t pos = it->rfind('/', it->length() - 2);
  153. if (it->at(pos + 1) == '.')
  154. it = foundFolders.erase(it);
  155. else
  156. ++it;
  157. }
  158. }
  159. for (unsigned long i = 0; i < foundFiles.size(); i++)
  160. files.emplace_back(File(foundFiles.at(i)));
  161. for (unsigned long i = 0; i < foundFolders.size(); i++)
  162. folders.emplace_back(Folder(foundFolders.at(i)));
  163. hasListed = true;
  164. }
  165. #ifdef USE_DIRENT
  166. int Folder::readFolderItems(std::vector<std::string> &foundFiles, std::vector<std::string> &foundFolders) {
  167. struct dirent entry;
  168. struct dirent *ep = nullptr;
  169. DIR *pakDir;
  170. pakDir = opendir(path.c_str());
  171. if (pakDir != nullptr) {
  172. readdir_r(pakDir, &entry, &ep);
  173. while (ep != nullptr) {
  174. if ((strcmp(".", ep->d_name) != 0)
  175. && (strcmp("..", ep->d_name) != 0)) {
  176. std::string tmp(path);
  177. if (tmp.back() != '/')
  178. tmp += '/';
  179. tmp += ep->d_name;
  180. if (ep->d_type == DT_DIR) {
  181. if (tmp.back() != '/')
  182. tmp += '/';
  183. foundFolders.push_back(std::string(tmp));
  184. } else {
  185. foundFiles.push_back(std::string(tmp));
  186. }
  187. }
  188. readdir_r(pakDir, &entry, &ep);
  189. }
  190. closedir(pakDir);
  191. } else {
  192. return 1;
  193. }
  194. return 0;
  195. }
  196. #elif defined(USE_FINDFILE)
  197. int Folder::readFolderItems(std::vector<std::string> &foundFiles, std::vector<std::string> &foundFolders) {
  198. std::string tmp(path);
  199. tmp += "/*";
  200. WIN32_FIND_DATA fd;
  201. HANDLE hFind = FindFirstFile(tmp.c_str(), &fd);
  202. if (hFind == nullptr)
  203. return 1;
  204. do {
  205. std::string s(path);
  206. s = s + "/" + fd.cFileName;
  207. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  208. foundFolders.push_back(s);
  209. else
  210. foundFiles.push_back(s);
  211. } while (FindNextFile(hFind, &fd) != 0);
  212. FindClose(hFind);
  213. return 0;
  214. }
  215. #endif