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.1KB

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