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 5.7KB

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