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

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