summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-08-05 16:12:55 -0400
committerGitHub <noreply@github.com>2020-08-05 16:12:55 -0400
commit3231048b328551edff9a923dec3f7bd46ed5aff8 (patch)
tree844e82463e964afb04bca1deb85acfda1bdc56a2 /source/core
parente713b56a63dcbf945e3e0e6d82666318795c74ff (diff)
Refactor enumerating directory contents (#1478)
* Use m_style for OSFindFilesResult * Refactor of FindFilesResult. * Fixes on linux for FindFiles. * Simplify FindFilesState, and linux support for pattern matching. * Small fixes to linux FindFilesState * Fix typo on linux FindFiles * Fix typo in linux FindFiles. * Renamed some variables, and improved comments on FindFiles. * Improve comments on FildFiles * Small improvements around FindFiles. * Refactor FindFiles again.. into a visitor and function in Path. * Fix some problems on linux. * Fix linux typo. * Renamed os -> find-file-util * find-file-utl -> directory-util Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
Diffstat (limited to 'source/core')
-rw-r--r--source/core/slang-io.cpp96
-rw-r--r--source/core/slang-io.h31
2 files changed, 127 insertions, 0 deletions
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index 1717c8354..5cbe021a2 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -19,6 +19,11 @@
#if defined(__linux__) || defined(__CYGWIN__) || SLANG_APPLE_FAMILY
# include <unistd.h>
+// For Path::find
+# include <fnmatch.h>
+
+# include <dirent.h>
+# include <sys/stat.h>
#endif
#if SLANG_APPLE_FAMILY
@@ -552,6 +557,97 @@ namespace Slang
#endif
}
+#if defined(_WIN32)
+ /* static */SlangResult Path::find(const String& directoryPath, const char* pattern, Visitor* visitor)
+ {
+ pattern = pattern ? pattern : "*";
+ String searchPath = Path::combine(directoryPath, pattern);
+
+ WIN32_FIND_DATAW fileData;
+
+ HANDLE findHandle = FindFirstFileW(searchPath.toWString(), &fileData);
+ if (!findHandle)
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+
+ do
+ {
+ if (!((wcscmp(fileData.cFileName, L".") == 0) ||
+ (wcscmp(fileData.cFileName, L"..") == 0)))
+ {
+ const Type type = (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? Type::Directory : Type::File;
+
+ String filename = String::fromWString(fileData.cFileName);
+ visitor->accept(type, filename.getUnownedSlice());
+ }
+ }
+ while (FindNextFileW(findHandle, &fileData) != 0);
+
+ ::FindClose(findHandle);
+ return SLANG_OK;
+ }
+#else
+ /* static */SlangResult Path::find(const String& directoryPath, const char* pattern, Visitor* visitor)
+ {
+ DIR* directory = opendir(directoryPath.getBuffer());
+
+ if (!directory)
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+
+ StringBuilder builder;
+ for (;;)
+ {
+ dirent* entry = readdir(directory);
+ if (entry == nullptr)
+ {
+ break;
+ }
+
+ if (strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
+ {
+ continue;
+ }
+
+ // If there is a pattern, check if it matches, and if it doesn't ignore it
+ if (pattern && fnmatch(pattern, entry->d_name, 0) != 0)
+ {
+ continue;
+ }
+
+ const UnownedStringSlice filename(entry->d_name);
+
+ // Produce the full path, to do stat
+ Path::combineIntoBuilder(directoryPath.getUnownedSlice(), filename, builder);
+
+ // fprintf(stderr, "stat(%s)\n", path.getBuffer());
+ struct stat fileInfo;
+ if (stat(builder.getBuffer(), &fileInfo) != 0)
+ {
+ continue;
+ }
+
+ Type type = Type::Unknown;
+ if (S_ISDIR(fileInfo.st_mode))
+ {
+ type = Type::Directory;
+ }
+ else if (S_ISREG(fileInfo.st_mode))
+ {
+ type = Type::File;
+ }
+
+ visitor->accept(type, filename);
+ }
+
+ closedir(directory);
+ return SLANG_OK;
+ }
+#endif
+
/// Gets the path to the executable that was invoked that led to the current threads execution
/// If run from a shared library/dll will be the path of the executable that loaded said library
/// @param outPath Pointer to buffer to hold the path.
diff --git a/source/core/slang-io.h b/source/core/slang-io.h
index b3d03d9a4..492723602 100644
--- a/source/core/slang-io.h
+++ b/source/core/slang-io.h
@@ -25,8 +25,39 @@ namespace Slang
class Path
{
public:
+
+ enum class Type
+ {
+ Unknown,
+ File,
+ Directory,
+ };
+
+ typedef uint32_t TypeFlags;
+ struct TypeFlag
+ {
+ enum Enum : TypeFlags
+ {
+ Unknown = TypeFlags(1) << int(Type::Unknown),
+ File = TypeFlags(1) << int(Type::File),
+ Directory = TypeFlags(1) << int(Type::Directory),
+ };
+ };
+
+ class Visitor
+ {
+ public:
+ virtual void accept(Type type, const UnownedStringSlice& filename) = 0;
+ };
+
static const char kPathDelimiter = '/';
+ /// Finds all all the items in the specified directory, that matches the pattern.
+ ///
+ /// @param directoryPath The directory to do the search in. If the directory is not found, SLANG_E_NOT_FOUND is returned
+ /// @param pattern. The pattern to match against. The pattern matching is targtet specific (ie window matching is different to linux/unix). Passing nullptr means no matching.
+ /// @return is SLANG_E_NOT_FOUND if the directoryPath is not found
+ static SlangResult find(const String& directoryPath, const char* pattern, Visitor* visitor);
/// Returns -1 if no separator is found
static Index findLastSeparatorIndex(String const& path);