diff options
Diffstat (limited to 'base/file_util_win.cc')
-rw-r--r-- | base/file_util_win.cc | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/base/file_util_win.cc b/base/file_util_win.cc index b166322..964302a 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -595,6 +595,139 @@ bool SetCurrentDirectory(const FilePath& directory) { return ret != 0; } +/////////////////////////////////////////////// +// FileEnumerator + +FileEnumerator::FileEnumerator(const FilePath& root_path, + bool recursive, + int file_type) + : recursive_(recursive), + file_type_(file_type), + has_find_data_(false), + find_handle_(INVALID_HANDLE_VALUE) { + // INCLUDE_DOT_DOT must not be specified if recursive. + DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); + memset(&find_data_, 0, sizeof(find_data_)); + pending_paths_.push(root_path); +} + +FileEnumerator::FileEnumerator(const FilePath& root_path, + bool recursive, + int file_type, + const FilePath::StringType& pattern) + : recursive_(recursive), + file_type_(file_type), + has_find_data_(false), + pattern_(pattern), + find_handle_(INVALID_HANDLE_VALUE) { + // INCLUDE_DOT_DOT must not be specified if recursive. + DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_))); + memset(&find_data_, 0, sizeof(find_data_)); + pending_paths_.push(root_path); +} + +FileEnumerator::~FileEnumerator() { + if (find_handle_ != INVALID_HANDLE_VALUE) + FindClose(find_handle_); +} + +void FileEnumerator::GetFindInfo(FindInfo* info) { + DCHECK(info); + + if (!has_find_data_) + return; + + memcpy(info, &find_data_, sizeof(*info)); +} + +// static +bool FileEnumerator::IsDirectory(const FindInfo& info) { + return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +// static +FilePath FileEnumerator::GetFilename(const FindInfo& find_info) { + return FilePath(find_info.cFileName); +} + +// static +int64 FileEnumerator::GetFilesize(const FindInfo& find_info) { + ULARGE_INTEGER size; + size.HighPart = find_info.nFileSizeHigh; + size.LowPart = find_info.nFileSizeLow; + DCHECK_LE(size.QuadPart, std::numeric_limits<int64>::max()); + return static_cast<int64>(size.QuadPart); +} + +// static +base::Time FileEnumerator::GetLastModifiedTime(const FindInfo& find_info) { + return base::Time::FromFileTime(find_info.ftLastWriteTime); +} + +FilePath FileEnumerator::Next() { + base::ThreadRestrictions::AssertIOAllowed(); + + while (has_find_data_ || !pending_paths_.empty()) { + if (!has_find_data_) { + // The last find FindFirstFile operation is done, prepare a new one. + root_path_ = pending_paths_.top(); + pending_paths_.pop(); + + // Start a new find operation. + FilePath src = root_path_; + + if (pattern_.empty()) + src = src.Append(L"*"); // No pattern = match everything. + else + src = src.Append(pattern_); + + find_handle_ = FindFirstFile(src.value().c_str(), &find_data_); + has_find_data_ = true; + } else { + // Search for the next file/directory. + if (!FindNextFile(find_handle_, &find_data_)) { + FindClose(find_handle_); + find_handle_ = INVALID_HANDLE_VALUE; + } + } + + if (INVALID_HANDLE_VALUE == find_handle_) { + has_find_data_ = false; + + // This is reached when we have finished a directory and are advancing to + // the next one in the queue. We applied the pattern (if any) to the files + // in the root search directory, but for those directories which were + // matched, we want to enumerate all files inside them. This will happen + // when the handle is empty. + pattern_ = FilePath::StringType(); + + continue; + } + + FilePath cur_file(find_data_.cFileName); + if (ShouldSkip(cur_file)) + continue; + + // Construct the absolute filename. + cur_file = root_path_.Append(find_data_.cFileName); + + if (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (recursive_) { + // If |cur_file| is a directory, and we are doing recursive searching, + // add it to pending_paths_ so we scan it after we finish scanning this + // directory. + pending_paths_.push(cur_file); + } + if (file_type_ & FileEnumerator::DIRECTORIES) + return cur_file; + } else if (file_type_ & FileEnumerator::FILES) { + return cur_file; + } + } + + return FilePath(); +} + bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { base::ThreadRestrictions::AssertIOAllowed(); FilePath mapped_file; |