From 42523379d983a693f8a358f79229951563057997 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 18 Apr 2024 00:04:46 +0100 Subject: [PATCH] Codechange: Use directory_iterator in ScanPath. Replaces use of custom ttd_opendir. --- src/fileio.cpp | 58 +++++++++++++++++++---------------------------- src/fileio_func.h | 4 ++-- src/fios.cpp | 4 ++-- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 285d7e471f..803baa60f2 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1134,12 +1134,13 @@ std::unique_ptr ReadFileToMem(const std::string &filename, size_t &lenp, * @param filename The filename to look in for the extension. * @return True iff the extension is nullptr, or the filename ends with it. */ -static bool MatchesExtension(const char *extension, const char *filename) +static bool MatchesExtension(std::string_view extension, const std::string &filename) { - if (extension == nullptr) return true; + if (extension.empty()) return true; + if (filename.length() < extension.length()) return false; - const char *ext = strrchr(filename, extension[0]); - return ext != nullptr && StrEqualsIgnoreCase(ext, extension); + std::string_view filename_sv = filename; // String view to avoid making another copy of the substring. + return StrCompareIgnoreCase(extension, filename_sv.substr(filename_sv.length() - extension.length())) == 0; } /** @@ -1151,36 +1152,24 @@ static bool MatchesExtension(const char *extension, const char *filename) * @param basepath_length from where in the path are we 'based' on the search path * @param recursive whether to recursively search the sub directories */ -static uint ScanPath(FileScanner *fs, const char *extension, const char *path, size_t basepath_length, bool recursive) +static uint ScanPath(FileScanner *fs, std::string_view extension, const std::filesystem::path &path, size_t basepath_length, bool recursive) { uint num = 0; - struct stat sb; - struct dirent *dirent; - DIR *dir; - if (path == nullptr || (dir = ttd_opendir(path)) == nullptr) return 0; - - while ((dirent = readdir(dir)) != nullptr) { - std::string d_name = FS2OTTD(dirent->d_name); - - if (!FiosIsValidFile(path, dirent, &sb)) continue; - - std::string filename(path); - filename += d_name; - - if (S_ISDIR(sb.st_mode)) { - /* Directory */ + std::error_code error_code; + for (const auto &dir_entry : std::filesystem::directory_iterator(path, error_code)) { + if (dir_entry.is_directory()) { if (!recursive) continue; - if (d_name == "." || d_name == "..") continue; - AppendPathSeparator(filename); - num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive); - } else if (S_ISREG(sb.st_mode)) { - /* File */ - if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, basepath_length, {})) num++; + num += ScanPath(fs, extension, dir_entry.path(), basepath_length, recursive); + } else if (dir_entry.is_regular_file()) { + std::string file = FS2OTTD(dir_entry.path()); + if (!MatchesExtension(extension, file)) continue; + if (fs->AddFile(file, basepath_length, {})) num++; } } - - closedir(dir); + if (error_code) { + Debug(misc, 9, "Unable to read directory {}: {}", path.string(), error_code.message()); + } return num; } @@ -1191,12 +1180,11 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s * @param extension the extension of files to search for. * @param tar the tar to search in. */ -static uint ScanTar(FileScanner *fs, const char *extension, const TarFileList::value_type &tar) +static uint ScanTar(FileScanner *fs, std::string_view extension, const TarFileList::value_type &tar) { uint num = 0; - const auto &filename = tar.first; - if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, 0, tar.second.tar_filename)) num++; + if (MatchesExtension(extension, tar.first) && fs->AddFile(tar.first, 0, tar.second.tar_filename)) num++; return num; } @@ -1210,7 +1198,7 @@ static uint ScanTar(FileScanner *fs, const char *extension, const TarFileList::v * @return the number of found files, i.e. the number of times that * AddFile returned true. */ -uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool recursive) +uint FileScanner::Scan(std::string_view extension, Subdirectory sd, bool tars, bool recursive) { this->subdir = sd; @@ -1221,7 +1209,7 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; std::string path = FioGetDirectory(sp, sd); - num += ScanPath(this, extension, path.c_str(), path.size(), recursive); + num += ScanPath(this, extension, OTTD2FS(path), path.size(), recursive); } if (tars && sd != NO_DIRECTORY) { @@ -1252,9 +1240,9 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r * @return the number of found files, i.e. the number of times that * AddFile returned true. */ -uint FileScanner::Scan(const char *extension, const std::string &directory, bool recursive) +uint FileScanner::Scan(const std::string_view extension, const std::string &directory, bool recursive) { std::string path(directory); AppendPathSeparator(path); - return ScanPath(this, extension, path.c_str(), path.size(), recursive); + return ScanPath(this, extension, OTTD2FS(path), path.size(), recursive); } diff --git a/src/fileio_func.h b/src/fileio_func.h index 2a13a454d4..9e85f1f8c0 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -42,8 +42,8 @@ public: /** Destruct the proper one... */ virtual ~FileScanner() = default; - uint Scan(const char *extension, Subdirectory sd, bool tars = true, bool recursive = true); - uint Scan(const char *extension, const std::string &directory, bool recursive = true); + uint Scan(std::string_view extension, Subdirectory sd, bool tars = true, bool recursive = true); + uint Scan(std::string_view extension, const std::string &directory, bool recursive = true); /** * Add a file with the given filename. diff --git a/src/fios.cpp b/src/fios.cpp index dd98cb6699..f5523c85aa 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -365,9 +365,9 @@ static void FiosGetFileList(SaveLoadOperation fop, bool show_dirs, FiosGetTypeAn /* Show files */ FiosFileScanner scanner(fop, callback_proc, file_list); if (subdir == NO_DIRECTORY) { - scanner.Scan(nullptr, *_fios_path, false); + scanner.Scan({}, *_fios_path, false); } else { - scanner.Scan(nullptr, subdir, true, true); + scanner.Scan({}, subdir, true, true); } std::sort(file_list.begin() + sort_start, file_list.end());