Open Source Tomb Raider Engine
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

Folder.cpp 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 = path.rfind('/', path.length() - 2);
  52. name = path.substr(last + 1);
  53. if (name.back() == '/')
  54. name.erase(name.length() - 1);
  55. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  56. if (path.back() != '/')
  57. path.append(1, '/');
  58. hasListed = false;
  59. listDot = listDotFiles;
  60. }
  61. std::string &Folder::getName() {
  62. return name;
  63. }
  64. std::string &Folder::getPath() {
  65. return path;
  66. }
  67. unsigned long Folder::fileCount() {
  68. createFolderItems();
  69. return files.size();
  70. }
  71. File &Folder::getFile(unsigned long i) {
  72. createFolderItems();
  73. assert(i < files.size());
  74. return files.at(i);
  75. }
  76. unsigned long Folder::folderCount() {
  77. createFolderItems();
  78. return folders.size();
  79. }
  80. Folder &Folder::getFolder(unsigned long i) {
  81. createFolderItems();
  82. assert(i < folders.size());
  83. return folders.at(i);
  84. }
  85. unsigned long Folder::countRecursiveItems() {
  86. unsigned long count = fileCount();
  87. for (unsigned long i = 0; i < folderCount(); i++)
  88. count += getFolder(i).countRecursiveItems();
  89. return count;
  90. }
  91. void Folder::executeRemoveRecursiveItems(std::function<bool (File &f)> func) {
  92. for (unsigned long i = 0; i < fileCount(); i++) {
  93. if (func(getFile(i))) {
  94. files.erase(files.begin() + (long)i--);
  95. }
  96. }
  97. for (unsigned long i = 0; i < folderCount(); i++) {
  98. getFolder(i).executeRemoveRecursiveItems(func);
  99. }
  100. }
  101. std::string Folder::getRecursiveItemName(unsigned long i) {
  102. assert(i < countRecursiveItems());
  103. if (i < fileCount()) {
  104. return getFile(i).getName();
  105. } else {
  106. unsigned long count = fileCount();
  107. for (unsigned long n = 0; n < folderCount(); n++) {
  108. if ((i - count) < getFolder(n).countRecursiveItems()) {
  109. return getFolder(n).getName() + '/'
  110. + getFolder(n).getRecursiveItemName(i - count);
  111. }
  112. count += getFolder(n).countRecursiveItems();
  113. }
  114. }
  115. assert(false);
  116. return "";
  117. }
  118. /*
  119. File &Folder::getRecursiveItem(unsigned long i) {
  120. assert(i < countRecursiveItems());
  121. if (i < fileCount()) {
  122. return getFile(i);
  123. } else {
  124. unsigned long count = fileCount();
  125. for (unsigned long n = 0; n < folderCount(); n++) {
  126. if ((i - count) < getFolder(n).countRecursiveItems()) {
  127. return getFolder(n).getRecursiveItem(i - count);
  128. }
  129. count += getFolder(n).countRecursiveItems();
  130. }
  131. }
  132. assert(false);
  133. return files.at(0);
  134. }
  135. */
  136. void Folder::createFolderItems() {
  137. if (hasListed)
  138. return;
  139. std::vector<std::string> foundFiles, foundFolders;
  140. if (readFolderItems(foundFiles, foundFolders) != 0)
  141. throw Exception(std::string("Could not open folder ") + name);
  142. if (!listDot) {
  143. std::vector<std::string>::iterator it = foundFiles.begin();
  144. while (it != foundFiles.end()) {
  145. size_t pos = it->rfind('/', it->length() - 2);
  146. if (it->at(pos + 1) == '.')
  147. it = foundFiles.erase(it);
  148. else
  149. ++it;
  150. }
  151. it = foundFolders.begin();
  152. while (it != foundFolders.end()) {
  153. size_t pos = it->rfind('/', it->length() - 2);
  154. if (it->at(pos + 1) == '.')
  155. it = foundFolders.erase(it);
  156. else
  157. ++it;
  158. }
  159. }
  160. for (unsigned long i = 0; i < foundFiles.size(); i++)
  161. files.emplace_back(File(foundFiles.at(i)));
  162. for (unsigned long i = 0; i < foundFolders.size(); i++)
  163. folders.emplace_back(Folder(foundFolders.at(i)));
  164. hasListed = true;
  165. }
  166. #ifdef USE_DIRENT
  167. int Folder::readFolderItems(std::vector<std::string> &foundFiles, std::vector<std::string> &foundFolders) {
  168. struct dirent entry;
  169. struct dirent *ep = nullptr;
  170. DIR *pakDir;
  171. pakDir = opendir(path.c_str());
  172. if (pakDir != nullptr) {
  173. readdir_r(pakDir, &entry, &ep);
  174. while (ep != nullptr) {
  175. if ((strcmp(".", ep->d_name) != 0)
  176. && (strcmp("..", ep->d_name) != 0)) {
  177. std::string tmp(path);
  178. if (tmp.back() != '/')
  179. tmp += '/';
  180. tmp += ep->d_name;
  181. if (ep->d_type == DT_DIR) {
  182. if (tmp.back() != '/')
  183. tmp += '/';
  184. foundFolders.push_back(std::string(tmp));
  185. } else {
  186. foundFiles.push_back(std::string(tmp));
  187. }
  188. }
  189. readdir_r(pakDir, &entry, &ep);
  190. }
  191. closedir(pakDir);
  192. } else {
  193. return 1;
  194. }
  195. return 0;
  196. }
  197. #elif defined(USE_FINDFILE)
  198. int Folder::readFolderItems(std::vector<std::string> &foundFiles, std::vector<std::string> &foundFolders) {
  199. std::string tmp(path);
  200. tmp += "/*";
  201. WIN32_FIND_DATA fd;
  202. HANDLE hFind = FindFirstFile(tmp.c_str(), &fd);
  203. if (hFind == nullptr)
  204. return 1;
  205. do {
  206. std::string s(path);
  207. s = s + "/" + fd.cFileName;
  208. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  209. foundFolders.push_back(s);
  210. else
  211. foundFiles.push_back(s);
  212. } while (FindNextFile(hFind, &fd) != 0);
  213. FindClose(hFind);
  214. return 0;
  215. }
  216. #endif