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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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 "global.h"
  10. #include <Log.h>
  11. #include "utils/filesystem.h"
  12. #include "utils/strings.h"
  13. #include "utils/Folder.h"
  14. File::File(std::string file) : path(file) {
  15. size_t pos = file.rfind('/', file.length() - 2);
  16. name = file.substr(pos + 1);
  17. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  18. }
  19. // ----------------------------------------------------------------------------
  20. #if defined(HAVE_DIRENT_H) && defined(HAVE_OPENDIR) && defined(HAVE_READDIR_R) && defined(HAVE_CLOSEDIR) && defined(HAVE_DT_DIR)
  21. #include <dirent.h>
  22. #define USE_DIRENT
  23. #elif defined (_WIN32)
  24. #include <windows.h>
  25. #define USE_FINDFILE
  26. #else
  27. #error No support for recursive folder traversal
  28. #endif
  29. Folder::Folder(std::string folder, bool listDotFiles) {
  30. if (((folder.length() == 0) || (folder.compare(".") == 0))
  31. #ifdef _WIN32
  32. || ((folder.compare(1, 2, std::string(":\\")) != 0) && (folder.at(0) != '~'))
  33. #else
  34. || ((folder.at(0) != '/') && (folder.at(0) != '~'))
  35. #endif
  36. ) {
  37. // Prepend current working directory
  38. path = getCurrentWorkingDirectory();
  39. if (folder.length() > 1)
  40. path += folder.substr(1);
  41. } else if (folder.at(0) == '~') {
  42. // Prepend home directory
  43. path = getHomeDirectory();
  44. std::cout << "Home: " << path << std::endl;
  45. if (folder.length() > 1)
  46. path += folder.substr(1);
  47. } else {
  48. path = folder;
  49. }
  50. // Find all '\\' replace with '/'
  51. size_t pos = path.find('\\');
  52. while (pos != std::string::npos) {
  53. path.at(pos) = '/';
  54. pos = path.find('\\');
  55. }
  56. size_t last = 0;
  57. if (path.length() > 1)
  58. last = path.rfind('/', path.length() - 2);
  59. name = path.substr(last + 1);
  60. if (name.back() == '/')
  61. name.erase(name.length() - 1);
  62. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  63. if (path.back() != '/')
  64. path.append(1, '/');
  65. hasListed = false;
  66. listDot = listDotFiles;
  67. }
  68. unsigned long Folder::fileCount() {
  69. createFolderItems();
  70. return files.size();
  71. }
  72. File& Folder::getFile(unsigned long i) {
  73. createFolderItems();
  74. assert(i < files.size());
  75. return files.at(i);
  76. }
  77. unsigned long Folder::folderCount() {
  78. createFolderItems();
  79. return folders.size();
  80. }
  81. Folder& Folder::getFolder(unsigned long i) {
  82. createFolderItems();
  83. assert(i < folders.size());
  84. return folders.at(i);
  85. }
  86. Folder Folder::getParent() {
  87. size_t last = path.rfind('/', path.length() - 2);
  88. std::string parent = path.substr(0, last);
  89. if (parent.length() == 0)
  90. parent = "/";
  91. return Folder(parent, listDot);
  92. }
  93. void Folder::executeRemoveFiles(std::function<bool (File& f)> func) {
  94. createFolderItems();
  95. for (unsigned long i = 0; i < fileCount(); i++) {
  96. if (func(getFile(i))) {
  97. files.erase(files.begin() + (long)i--);
  98. }
  99. }
  100. }
  101. void Folder::createFolderItems() {
  102. if (hasListed)
  103. return;
  104. std::vector<std::string> foundFiles, foundFolders;
  105. if (readFolderItems(foundFiles, foundFolders) != 0) {
  106. getLog() << "Could not open folder " << name << Log::endl;
  107. }
  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
  187. void Folder::findFilesEndingWith(std::vector<File>& found, std::string end, bool casesensitive) {
  188. createFolderItems();
  189. for (auto& f : files) {
  190. if (stringEndsWith(f.getName(), end, casesensitive))
  191. found.push_back(f);
  192. }
  193. }