| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef BASE_FILES_FILE_ENUMERATOR_H_ | |
| #define BASE_FILES_FILE_ENUMERATOR_H_ | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <vector> | |
| #include "base/containers/stack.h" | |
| #include "base/files/file_path.h" | |
| #include "base/macros.h" | |
| #include "util/build_config.h" | |
| #include "util/ticks.h" | |
| #if defined(OS_WIN) | |
| #include <windows.h> | |
| #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | |
| #include <sys/stat.h> | |
| #include <unistd.h> | |
| #endif | |
| namespace base { | |
| // A class for enumerating the files in a provided path. The order of the | |
| // results is not guaranteed. | |
| // | |
| // This is blocking. Do not use on critical threads. | |
| // | |
| // Example: | |
| // | |
| // base::FileEnumerator enum(my_dir, false, base::FileEnumerator::FILES, | |
| // FILE_PATH_LITERAL("*.txt")); | |
| // for (base::FilePath name = enum.Next(); !name.empty(); name = enum.Next()) | |
| // ... | |
| class FileEnumerator { | |
| public: | |
| // Note: copy & assign supported. | |
| class FileInfo { | |
| public: | |
| FileInfo(); | |
| ~FileInfo(); | |
| bool IsDirectory() const; | |
| // The name of the file. This will not include any path information. This | |
| // is in constrast to the value returned by FileEnumerator.Next() which | |
| // includes the |root_path| passed into the FileEnumerator constructor. | |
| FilePath GetName() const; | |
| int64_t GetSize() const; | |
| Ticks GetLastModifiedTime() const; | |
| #if defined(OS_WIN) | |
| // Note that the cAlternateFileName (used to hold the "short" 8.3 name) | |
| // of the WIN32_FIND_DATA will be empty. Since we don't use short file | |
| // names, we tell Windows to omit it which speeds up the query slightly. | |
| const WIN32_FIND_DATA& find_data() const { return find_data_; } | |
| #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | |
| const struct stat& stat() const { return stat_; } | |
| #endif | |
| private: | |
| friend class FileEnumerator; | |
| #if defined(OS_WIN) | |
| WIN32_FIND_DATA find_data_; | |
| #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | |
| struct stat stat_; | |
| FilePath filename_; | |
| #endif | |
| }; | |
| enum FileType { | |
| FILES = 1 << 0, | |
| DIRECTORIES = 1 << 1, | |
| INCLUDE_DOT_DOT = 1 << 2, | |
| #if defined(OS_POSIX) || defined(OS_FUCHSIA) | |
| SHOW_SYM_LINKS = 1 << 4, | |
| #endif | |
| }; | |
| // Search policy for intermediate folders. | |
| enum class FolderSearchPolicy { | |
| // Recursive search will pass through folders whose names match the | |
| // pattern. Inside each one, all files will be returned. Folders with names | |
| // that do not match the pattern will be ignored within their interior. | |
| MATCH_ONLY, | |
| // Recursive search will pass through every folder and perform pattern | |
| // matching inside each one. | |
| ALL, | |
| }; | |
| // |root_path| is the starting directory to search for. It may or may not end | |
| // in a slash. | |
| // | |
| // If |recursive| is true, this will enumerate all matches in any | |
| // subdirectories matched as well. It does a breadth-first search, so all | |
| // files in one directory will be returned before any files in a | |
| // subdirectory. | |
| // | |
| // |file_type|, a bit mask of FileType, specifies whether the enumerator | |
| // should match files, directories, or both. | |
| // | |
| // |pattern| is an optional pattern for which files to match. This | |
| // works like shell globbing. For example, "*.txt" or "Foo???.doc". | |
| // However, be careful in specifying patterns that aren't cross platform | |
| // since the underlying code uses OS-specific matching routines. In general, | |
| // Windows matching is less featureful than others, so test there first. | |
| // If unspecified, this will match all files. | |
| FileEnumerator(const FilePath& root_path, bool recursive, int file_type); | |
| FileEnumerator(const FilePath& root_path, | |
| bool recursive, | |
| int file_type, | |
| const FilePath::StringType& pattern); | |
| FileEnumerator(const FilePath& root_path, | |
| bool recursive, | |
| int file_type, | |
| const FilePath::StringType& pattern, | |
| FolderSearchPolicy folder_search_policy); | |
| ~FileEnumerator(); | |
| // Returns the next file or an empty string if there are no more results. | |
| // | |
| // The returned path will incorporate the |root_path| passed in the | |
| // constructor: "<root_path>/file_name.txt". If the |root_path| is absolute, | |
| // then so will be the result of Next(). | |
| FilePath Next(); | |
| // Write the file info into |info|. | |
| FileInfo GetInfo() const; | |
| private: | |
| // Returns true if the given path should be skipped in enumeration. | |
| bool ShouldSkip(const FilePath& path); | |
| bool IsTypeMatched(bool is_dir) const; | |
| bool IsPatternMatched(const FilePath& src) const; | |
| #if defined(OS_WIN) | |
| // True when find_data_ is valid. | |
| bool has_find_data_ = false; | |
| WIN32_FIND_DATA find_data_; | |
| HANDLE find_handle_ = INVALID_HANDLE_VALUE; | |
| #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | |
| // The files in the current directory | |
| std::vector<FileInfo> directory_entries_; | |
| // The next entry to use from the directory_entries_ vector | |
| size_t current_directory_entry_; | |
| #endif | |
| FilePath root_path_; | |
| const bool recursive_; | |
| const int file_type_; | |
| FilePath::StringType pattern_; | |
| const FolderSearchPolicy folder_search_policy_; | |
| // A stack that keeps track of which subdirectories we still need to | |
| // enumerate in the breadth-first search. | |
| base::stack<FilePath> pending_paths_; | |
| DISALLOW_COPY_AND_ASSIGN(FileEnumerator); | |
| }; | |
| } // namespace base | |
| #endif // BASE_FILES_FILE_ENUMERATOR_H_ |