diff --git a/hecl/extern/libBoo b/hecl/extern/libBoo index ce9d877cf..9c1735052 160000 --- a/hecl/extern/libBoo +++ b/hecl/extern/libBoo @@ -1 +1 @@ -Subproject commit ce9d877cfaeb63f8335acd36517b3026e6728d46 +Subproject commit 9c173505248875ee9bf7e943030a134401da6e05 diff --git a/hecl/include/HECL/HECL.hpp b/hecl/include/HECL/HECL.hpp index e19af2df5..c02a458d2 100644 --- a/hecl/include/HECL/HECL.hpp +++ b/hecl/include/HECL/HECL.hpp @@ -560,170 +560,11 @@ private: std::vector m_entries; public: - DirectoryEnumerator(const HECL::SystemString& path, Mode mode=Mode::DirsThenFilesSorted) - : DirectoryEnumerator(path.c_str(), mode) {} - DirectoryEnumerator(const HECL::SystemChar* path, Mode mode=Mode::DirsThenFilesSorted) - { - HECL::Sstat theStat; - if (HECL::Stat(path, &theStat) || !S_ISDIR(theStat.st_mode)) - return; -#if _WIN32 - HECL::SystemString wc(path); - wc += _S("/*"); - WIN32_FIND_DATAW d; - HANDLE dir = FindFirstFileW(wc.c_str(), &d); - if (dir == INVALID_HANDLE_VALUE) - return; - switch (mode) - { - case Mode::Native: - do - { - if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) - continue; - HECL::SystemString fp(path); - fp += _S('/'); - fp += d.cFileName; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st)) - continue; - - size_t sz = 0; - bool isDir = false; - if (S_ISDIR(st.st_mode)) - isDir = true; - else if (S_ISREG(st.st_mode)) - sz = st.st_size; - else - continue; - - m_entries.push_back(std::move(Entry(std::move(fp), d.cFileName, sz, isDir))); - } while (FindNextFileW(dir, &d)); - break; - case Mode::DirsThenFilesSorted: - case Mode::DirsSorted: - { - std::map sort; - do - { - if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) - continue; - HECL::SystemString fp(path); - fp +=_S('/'); - fp += d.cFileName; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode)) - continue; - sort.emplace(std::make_pair(d.cFileName, Entry(std::move(fp), d.cFileName, 0, true))); - } while (FindNextFileW(dir, &d)); - for (auto& e : sort) - m_entries.push_back(std::move(e.second)); - if (mode == Mode::DirsSorted) - break; - FindClose(dir); - dir = FindFirstFileW(wc.c_str(), &d); - } - case Mode::FilesSorted: - { - if (mode == Mode::FilesSorted) - m_entries.clear(); - std::map sort; - do - { - if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) - continue; - HECL::SystemString fp(path); - fp += _S('/'); - fp += d.cFileName; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) - continue; - sort.emplace(std::make_pair(d.cFileName, Entry(std::move(fp), d.cFileName, st.st_size, false))); - } while (FindNextFileW(dir, &d)); - for (auto& e : sort) - m_entries.push_back(std::move(e.second)); - break; - } - } - FindClose(dir); -#else - DIR* dir = opendir(path); - if (!dir) - return; - const dirent* d; - switch (mode) - { - case Mode::Native: - while ((d = readdir(dir))) - { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - HECL::SystemString fp(path); - fp += '/'; - fp += d->d_name; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st)) - continue; - - size_t sz = 0; - bool isDir = false; - if (S_ISDIR(st.st_mode)) - isDir = true; - else if (S_ISREG(st.st_mode)) - sz = st.st_size; - else - continue; - - m_entries.push_back(std::move(Entry(std::move(fp), d->d_name, sz, isDir))); - } - break; - case Mode::DirsThenFilesSorted: - case Mode::DirsSorted: - { - std::map sort; - while ((d = readdir(dir))) - { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - HECL::SystemString fp(path); - fp += '/'; - fp += d->d_name; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode)) - continue; - sort.emplace(std::make_pair(d->d_name, Entry(std::move(fp), d->d_name, 0, true))); - } - for (auto& e : sort) - m_entries.push_back(std::move(e.second)); - if (mode == Mode::DirsSorted) - break; - rewinddir(dir); - } - case Mode::FilesSorted: - { - if (mode == Mode::FilesSorted) - m_entries.clear(); - std::map sort; - while ((d = readdir(dir))) - { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - HECL::SystemString fp(path); - fp += '/'; - fp += d->d_name; - HECL::Sstat st; - if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) - continue; - sort.emplace(std::make_pair(d->d_name, Entry(std::move(fp), d->d_name, st.st_size, false))); - } - for (auto& e : sort) - m_entries.push_back(std::move(e.second)); - break; - } - } - closedir(dir); -#endif - } + DirectoryEnumerator(const HECL::SystemString& path, Mode mode=Mode::DirsThenFilesSorted, + bool sizeSort=false, bool reverse=false) + : DirectoryEnumerator(path.c_str(), mode, sizeSort, reverse) {} + DirectoryEnumerator(const HECL::SystemChar* path, Mode mode=Mode::DirsThenFilesSorted, + bool sizeSort=false, bool reverse=false); operator bool() const {return m_entries.size() != 0;} size_t size() const {return m_entries.size();} diff --git a/hecl/lib/HECL.cpp b/hecl/lib/HECL.cpp index cf74ceedc..d17c8ad92 100644 --- a/hecl/lib/HECL.cpp +++ b/hecl/lib/HECL.cpp @@ -117,4 +117,250 @@ bool IsPathYAML(const HECL::ProjectPath& path) return false; } +HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mode mode, + bool sizeSort, bool reverse) +{ + HECL::Sstat theStat; + if (HECL::Stat(path, &theStat) || !S_ISDIR(theStat.st_mode)) + return; + +#if _WIN32 + HECL::SystemString wc(path); + wc += _S("/*"); + WIN32_FIND_DATAW d; + HANDLE dir = FindFirstFileW(wc.c_str(), &d); + if (dir == INVALID_HANDLE_VALUE) + return; + switch (mode) + { + case Mode::Native: + do + { + if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) + continue; + HECL::SystemString fp(path); + fp += _S('/'); + fp += d.cFileName; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st)) + continue; + + size_t sz = 0; + bool isDir = false; + if (S_ISDIR(st.st_mode)) + isDir = true; + else if (S_ISREG(st.st_mode)) + sz = st.st_size; + else + continue; + + m_entries.push_back(std::move(Entry(std::move(fp), d.cFileName, sz, isDir))); + } while (FindNextFileW(dir, &d)); + break; + case Mode::DirsThenFilesSorted: + case Mode::DirsSorted: + { + std::map sort; + do + { + if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) + continue; + HECL::SystemString fp(path); + fp +=_S('/'); + fp += d.cFileName; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode)) + continue; + sort.emplace(std::make_pair(d.cFileName, Entry(std::move(fp), d.cFileName, 0, true))); + } while (FindNextFileW(dir, &d)); + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + + if (mode == Mode::DirsSorted) + break; + FindClose(dir); + dir = FindFirstFileW(wc.c_str(), &d); + } + case Mode::FilesSorted: + { + if (mode == Mode::FilesSorted) + m_entries.clear(); + + if (sizeSort) + { + std::map sort; + do + { + if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) + continue; + HECL::SystemString fp(path); + fp += _S('/'); + fp += d.cFileName; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) + continue; + sort.emplace(std::make_pair(st.st_size, Entry(std::move(fp), d.cFileName, st.st_size, false))); + } while (FindNextFileW(dir, &d)); + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + } + else + { + std::map sort; + do + { + if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S(".."))) + continue; + HECL::SystemString fp(path); + fp += _S('/'); + fp += d.cFileName; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) + continue; + sort.emplace(std::make_pair(d.cFileName, Entry(std::move(fp), d.cFileName, st.st_size, false))); + } while (FindNextFileW(dir, &d)); + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + } + + break; + } + } + FindClose(dir); + +#else + + DIR* dir = opendir(path); + if (!dir) + return; + const dirent* d; + switch (mode) + { + case Mode::Native: + while ((d = readdir(dir))) + { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + HECL::SystemString fp(path); + fp += '/'; + fp += d->d_name; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st)) + continue; + + size_t sz = 0; + bool isDir = false; + if (S_ISDIR(st.st_mode)) + isDir = true; + else if (S_ISREG(st.st_mode)) + sz = st.st_size; + else + continue; + + m_entries.push_back(std::move(Entry(std::move(fp), d->d_name, sz, isDir))); + } + break; + case Mode::DirsThenFilesSorted: + case Mode::DirsSorted: + { + std::map sort; + while ((d = readdir(dir))) + { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + HECL::SystemString fp(path); + fp += '/'; + fp += d->d_name; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode)) + continue; + sort.emplace(std::make_pair(d->d_name, Entry(std::move(fp), d->d_name, 0, true))); + } + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + + if (mode == Mode::DirsSorted) + break; + rewinddir(dir); + } + case Mode::FilesSorted: + { + if (mode == Mode::FilesSorted) + m_entries.clear(); + + if (sizeSort) + { + std::map sort; + while ((d = readdir(dir))) + { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + HECL::SystemString fp(path); + fp += '/'; + fp += d->d_name; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) + continue; + sort.emplace(std::make_pair(st.st_size, Entry(std::move(fp), d->d_name, st.st_size, false))); + } + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + } + else + { + std::map sort; + while ((d = readdir(dir))) + { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + HECL::SystemString fp(path); + fp += '/'; + fp += d->d_name; + HECL::Sstat st; + if (HECL::Stat(fp.c_str(), &st) || !S_ISREG(st.st_mode)) + continue; + sort.emplace(std::make_pair(d->d_name, Entry(std::move(fp), d->d_name, st.st_size, false))); + } + + if (reverse) + for (auto it=sort.crbegin() ; it != sort.crend() ; ++it) + m_entries.push_back(std::move(it->second)); + else + for (auto& e : sort) + m_entries.push_back(std::move(e.second)); + } + + break; + } + } + closedir(dir); + +#endif +} + }