From 78bc829886b414386e2ead07e0b52b7278bd3ef2 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 5 Apr 2026 19:55:59 +0100 Subject: [PATCH] Codechange: make Searchpath a scoped enum --- src/fileio.cpp | 90 ++++++++++++++++----------------- src/fileio_type.h | 26 +++++----- src/help_gui.cpp | 2 +- src/music/midifile.cpp | 2 +- src/network/network_content.cpp | 2 +- src/os/macosx/macos.mm | 8 +-- src/os/windows/win32.cpp | 32 ++++++------ 7 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index daca71e6b3..47e8d4c723 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -62,7 +62,7 @@ static const EnumClassIndexContainer _searchpaths; +EnumClassIndexContainer, Searchpath> _searchpaths; std::vector _valid_searchpaths; /** List of tar files found in each subdirectory. */ EnumClassIndexContainer, Subdirectory> _tar_list; @@ -76,7 +76,7 @@ EnumClassIndexContainer seen{}; - for (Searchpath sp = SP_FIRST_DIR; sp < NUM_SEARCHPATHS; sp++) { - if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; + for (Searchpath sp = Searchpath::Begin; sp < Searchpath::End; sp++) { + if (sp == Searchpath::WorkingDir && !_do_scan_working_directory) continue; if (only_local_path) { switch (sp) { - case SP_WORKING_DIR: // Can be influence by "-c" option. - case SP_BINARY_DIR: // Most likely contains all the language files. - case SP_AUTODOWNLOAD_DIR: // Otherwise we cannot download in-game content. + case Searchpath::WorkingDir: // Can be influence by "-c" option. + case Searchpath::BinaryDir: // Most likely contains all the language files. + case Searchpath::AutodownloadDir: // Otherwise we cannot download in-game content. break; default: @@ -109,8 +109,8 @@ static void FillValidSearchPaths(bool only_local_path) /* The working-directory is special, as it is controlled by _do_scan_working_directory. * Only add the search path if it isn't already in the set. To preserve the same order * as the enum, insert it in the front. */ - if (IsValidSearchPath(SP_WORKING_DIR) && seen.count(_searchpaths[SP_WORKING_DIR]) == 0) { - _valid_searchpaths.insert(_valid_searchpaths.begin(), SP_WORKING_DIR); + if (IsValidSearchPath(Searchpath::WorkingDir) && seen.count(_searchpaths[Searchpath::WorkingDir]) == 0) { + _valid_searchpaths.insert(_valid_searchpaths.begin(), Searchpath::WorkingDir); } } @@ -165,7 +165,7 @@ std::string FioFindFullPath(Subdirectory subdir, std::string_view filename) std::string FioGetDirectory(Searchpath sp, Subdirectory subdir) { assert(subdir < Subdirectory::End); - assert(sp < NUM_SEARCHPATHS); + assert(sp < Searchpath::End); return fmt::format("{}{}", _searchpaths[sp], _subdirs[subdir]); } @@ -720,18 +720,18 @@ static bool ChangeWorkingDirectoryToExecutable(std::string_view exe) bool DoScanWorkingDirectory() { /* No working directory, so nothing to do. */ - if (_searchpaths[SP_WORKING_DIR].empty()) return false; + if (_searchpaths[Searchpath::WorkingDir].empty()) return false; /* Working directory is root, so do nothing. */ - if (_searchpaths[SP_WORKING_DIR] == PATHSEP) return false; + if (_searchpaths[Searchpath::WorkingDir] == PATHSEP) return false; /* No personal/home directory, so the working directory won't be that. */ - if (_searchpaths[SP_PERSONAL_DIR].empty()) return true; + if (_searchpaths[Searchpath::PersonalDir].empty()) return true; - std::string tmp = _searchpaths[SP_WORKING_DIR] + PERSONAL_DIR; + std::string tmp = _searchpaths[Searchpath::WorkingDir] + PERSONAL_DIR; AppendPathSeparator(tmp); - return _searchpaths[SP_PERSONAL_DIR] != tmp; + return _searchpaths[Searchpath::PersonalDir] != tmp; } /** @@ -769,52 +769,52 @@ void DetermineBasePaths(std::string_view exe) tmp += PATHSEP; tmp += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_PERSONAL_DIR_XDG] = tmp; + _searchpaths[Searchpath::PersonalDirXdg] = tmp; tmp += "content_download"; AppendPathSeparator(tmp); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR_XDG] = tmp; + _searchpaths[Searchpath::AutodownloadPersonalDirXdg] = tmp; } else if (!homedir.empty()) { tmp = homedir; tmp += PATHSEP ".local" PATHSEP "share" PATHSEP; tmp += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_PERSONAL_DIR_XDG] = tmp; + _searchpaths[Searchpath::PersonalDirXdg] = tmp; tmp += "content_download"; AppendPathSeparator(tmp); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR_XDG] = tmp; + _searchpaths[Searchpath::AutodownloadPersonalDirXdg] = tmp; } else { - _searchpaths[SP_PERSONAL_DIR_XDG].clear(); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR_XDG].clear(); + _searchpaths[Searchpath::PersonalDirXdg].clear(); + _searchpaths[Searchpath::AutodownloadPersonalDirXdg].clear(); } #endif #if !defined(WITH_PERSONAL_DIR) - _searchpaths[SP_PERSONAL_DIR].clear(); + _searchpaths[Searchpath::PersonalDir].clear(); #else if (!homedir.empty()) { tmp = std::move(homedir); tmp += PATHSEP; tmp += PERSONAL_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_PERSONAL_DIR] = tmp; + _searchpaths[Searchpath::PersonalDir] = tmp; tmp += "content_download"; AppendPathSeparator(tmp); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR] = tmp; + _searchpaths[Searchpath::AutodownloadPersonalDir] = tmp; } else { - _searchpaths[SP_PERSONAL_DIR].clear(); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR].clear(); + _searchpaths[Searchpath::PersonalDir].clear(); + _searchpaths[Searchpath::AutodownloadPersonalDir].clear(); } #endif #if defined(WITH_SHARED_DIR) tmp = SHARED_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_SHARED_DIR] = tmp; + _searchpaths[Searchpath::SharedDir] = tmp; #else - _searchpaths[SP_SHARED_DIR].clear(); + _searchpaths[Searchpath::SharedDir].clear(); #endif char cwd[MAX_PATH]; @@ -824,7 +824,7 @@ void DetermineBasePaths(std::string_view exe) /* Get the path to working directory of OpenTTD. */ tmp = cwd; AppendPathSeparator(tmp); - _searchpaths[SP_WORKING_DIR] = tmp; + _searchpaths[Searchpath::WorkingDir] = tmp; _do_scan_working_directory = DoScanWorkingDirectory(); } else { @@ -837,7 +837,7 @@ void DetermineBasePaths(std::string_view exe) tmp = FS2OTTD(std::filesystem::weakly_canonical(std::filesystem::path(OTTD2FS(_config_file))).parent_path().native()); } AppendPathSeparator(tmp); - _searchpaths[SP_WORKING_DIR] = tmp; + _searchpaths[Searchpath::WorkingDir] = tmp; } /* Change the working directory to that one of the executable */ @@ -849,9 +849,9 @@ void DetermineBasePaths(std::string_view exe) tmp = buf; } AppendPathSeparator(tmp); - _searchpaths[SP_BINARY_DIR] = tmp; + _searchpaths[Searchpath::BinaryDir] = tmp; } else { - _searchpaths[SP_BINARY_DIR].clear(); + _searchpaths[Searchpath::BinaryDir].clear(); } if (cwd[0] != '\0') { @@ -862,17 +862,17 @@ void DetermineBasePaths(std::string_view exe) } #if !defined(GLOBAL_DATA_DIR) - _searchpaths[SP_INSTALLATION_DIR].clear(); + _searchpaths[Searchpath::InstallationDir].clear(); #else tmp = GLOBAL_DATA_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_INSTALLATION_DIR] = std::move(tmp); + _searchpaths[Searchpath::InstallationDir] = std::move(tmp); #endif #ifdef WITH_COCOA extern void CocoaSetApplicationBundleDir(); CocoaSetApplicationBundleDir(); #else - _searchpaths[SP_APPLICATION_BUNDLE_DIR].clear(); + _searchpaths[Searchpath::ApplicationBundleDir].clear(); #endif } #endif /* defined(_WIN32) */ @@ -908,13 +908,13 @@ void DeterminePaths(std::string_view exe, bool only_local_path) #endif for (Searchpath sp : _valid_searchpaths) { - if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; + if (sp == Searchpath::WorkingDir && !_do_scan_working_directory) continue; Debug(misc, 3, "{} added as search path", _searchpaths[sp]); } std::string config_dir; if (!_config_file.empty()) { - config_dir = _searchpaths[SP_WORKING_DIR]; + config_dir = _searchpaths[Searchpath::WorkingDir]; } else { std::string personal_dir = FioFindFullPath(Subdirectory::Base, "openttd.cfg"); if (!personal_dir.empty()) { @@ -927,7 +927,7 @@ void DeterminePaths(std::string_view exe, bool only_local_path) config_dir = config_home; #else static const Searchpath new_openttd_cfg_order[] = { - SP_PERSONAL_DIR, SP_BINARY_DIR, SP_WORKING_DIR, SP_SHARED_DIR, SP_INSTALLATION_DIR + Searchpath::PersonalDir, Searchpath::BinaryDir, Searchpath::WorkingDir, Searchpath::SharedDir, Searchpath::InstallationDir }; config_dir.clear(); @@ -960,13 +960,13 @@ void DeterminePaths(std::string_view exe, bool only_local_path) if (config_dir == config_home) { /* We are using the XDG configuration home for the config file, * then store the rest in the XDG data home folder. */ - _personal_dir = _searchpaths[SP_PERSONAL_DIR_XDG]; + _personal_dir = _searchpaths[Searchpath::PersonalDirXdg]; if (only_local_path) { /* In case of XDG and we only want local paths and we detected that * the user either manually indicated the XDG path or didn't use * "-c" option, we change the working-dir to the XDG personal-dir, * as this is most likely what the user is expecting. */ - _searchpaths[SP_WORKING_DIR] = _searchpaths[SP_PERSONAL_DIR_XDG]; + _searchpaths[Searchpath::WorkingDir] = _searchpaths[Searchpath::PersonalDirXdg]; } } else #endif @@ -991,15 +991,15 @@ void DeterminePaths(std::string_view exe, bool only_local_path) } /* If we have network we make a directory for the autodownloading of content */ - _searchpaths[SP_AUTODOWNLOAD_DIR] = _personal_dir + "content_download" PATHSEP; - Debug(misc, 3, "{} added as search path", _searchpaths[SP_AUTODOWNLOAD_DIR]); - FioCreateDirectory(_searchpaths[SP_AUTODOWNLOAD_DIR]); + _searchpaths[Searchpath::AutodownloadDir] = _personal_dir + "content_download" PATHSEP; + Debug(misc, 3, "{} added as search path", _searchpaths[Searchpath::AutodownloadDir]); + FioCreateDirectory(_searchpaths[Searchpath::AutodownloadDir]); FillValidSearchPaths(only_local_path); /* Create the directory for each of the types of content */ const Subdirectory subdirs[] = { Subdirectory::Scenario, Subdirectory::Heightmap, Subdirectory::Baseset, Subdirectory::NewGrf, Subdirectory::Ai, Subdirectory::AiLibrary, Subdirectory::Gs, Subdirectory::GsLibrary, Subdirectory::SocialIntegration }; for (const auto &subdir : subdirs) { - FioCreateDirectory(FioGetDirectory(SP_AUTODOWNLOAD_DIR, subdir)); + FioCreateDirectory(FioGetDirectory(Searchpath::AutodownloadDir, subdir)); } extern std::string _log_file; @@ -1131,7 +1131,7 @@ uint FileScanner::Scan(std::string_view extension, Subdirectory sd, bool tars, b for (Searchpath sp : _valid_searchpaths) { /* Don't search in the working directory */ - if (sp == SP_WORKING_DIR && !_do_scan_working_directory) continue; + if (sp == Searchpath::WorkingDir && !_do_scan_working_directory) continue; std::string path = FioGetDirectory(sp, sd); num += ScanPath(this, extension, OTTD2FS(path), path.size(), recursive); diff --git a/src/fileio_type.h b/src/fileio_type.h index a46d4c1035..208dd43ce6 100644 --- a/src/fileio_type.h +++ b/src/fileio_type.h @@ -110,21 +110,21 @@ enum class Subdirectory : uint8_t { /** * Types of searchpaths OpenTTD might use */ -enum Searchpath : uint8_t { - SP_FIRST_DIR, - SP_WORKING_DIR = SP_FIRST_DIR, ///< Search in the working directory +enum class Searchpath : uint8_t { + Begin, ///< The lowest valid value. + WorkingDir = Searchpath::Begin, ///< Search in the working directory. #ifdef USE_XDG - SP_PERSONAL_DIR_XDG, ///< Search in the personal directory from the XDG specification + PersonalDirXdg, ///< Search in the personal directory from the XDG specification. #endif - SP_PERSONAL_DIR, ///< Search in the personal directory - SP_SHARED_DIR, ///< Search in the shared directory, like 'Shared Files' under Windows - SP_BINARY_DIR, ///< Search in the directory where the binary resides - SP_INSTALLATION_DIR, ///< Search in the installation directory - SP_APPLICATION_BUNDLE_DIR, ///< Search within the application bundle - SP_AUTODOWNLOAD_DIR, ///< Search within the autodownload directory - SP_AUTODOWNLOAD_PERSONAL_DIR, ///< Search within the autodownload directory located in the personal directory - SP_AUTODOWNLOAD_PERSONAL_DIR_XDG, ///< Search within the autodownload directory located in the personal directory (XDG variant) - NUM_SEARCHPATHS + PersonalDir, ///< Search in the personal directory. + SharedDir, ///< Search in the shared directory, like 'Shared Files' under Windows. + BinaryDir, ///< Search in the directory where the binary resides. + InstallationDir, ///< Search in the installation directory. + ApplicationBundleDir, ///< Search within the application bundle. + AutodownloadDir, ///< Search within the autodownload directory. + AutodownloadPersonalDir,///< Search within the autodownload directory located in the personal directory. + AutodownloadPersonalDirXdg, ///< Search within the autodownload directory located in the personal directory (XDG variant). + End, ///< End marker. }; DECLARE_INCREMENT_DECREMENT_OPERATORS(Searchpath) diff --git a/src/help_gui.cpp b/src/help_gui.cpp index 94d973c74a..6a532a68df 100644 --- a/src/help_gui.cpp +++ b/src/help_gui.cpp @@ -48,7 +48,7 @@ static constexpr size_t CHANGELOG_VERSIONS_LIMIT = 20; static std::optional FindGameManualFilePath(std::string_view filename, Subdirectory subdir) { static const Searchpath searchpaths[] = { - SP_APPLICATION_BUNDLE_DIR, SP_INSTALLATION_DIR, SP_SHARED_DIR, SP_BINARY_DIR, SP_WORKING_DIR + Searchpath::ApplicationBundleDir, Searchpath::InstallationDir, Searchpath::SharedDir, Searchpath::BinaryDir, Searchpath::WorkingDir }; for (Searchpath sp : searchpaths) { diff --git a/src/music/midifile.cpp b/src/music/midifile.cpp index 9f5f247c46..4bb34aa1c1 100644 --- a/src/music/midifile.cpp +++ b/src/music/midifile.cpp @@ -1049,7 +1049,7 @@ std::string MidiFile::GetSMFFile(const MusicSongInfo &song) if (song.filetype != MTT_MPSMIDI) return std::string(); - std::string tempdirname = FioGetDirectory(Searchpath::SP_AUTODOWNLOAD_DIR, Subdirectory::Baseset); + std::string tempdirname = FioGetDirectory(Searchpath::AutodownloadDir, Subdirectory::Baseset); { std::string_view basename{song.filename}; auto fnstart = basename.rfind(PATHSEPCHAR); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index 46dc31bb0e..76d0a6dbbd 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -372,7 +372,7 @@ static std::string GetFullFilename(const ContentInfo &ci, bool compressed) Subdirectory dir = GetContentInfoSubDir(ci.type); if (dir == Subdirectory::None) return {}; - std::string buf = FioGetDirectory(SP_AUTODOWNLOAD_DIR, dir); + std::string buf = FioGetDirectory(Searchpath::AutodownloadDir, dir); buf += ci.filename; buf += compressed ? ".tar.gz" : ".tar"; diff --git a/src/os/macosx/macos.mm b/src/os/macosx/macos.mm index 3125be98f6..c8e134588a 100644 --- a/src/os/macosx/macos.mm +++ b/src/os/macosx/macos.mm @@ -126,15 +126,15 @@ std::optional GetClipboardContents() */ void CocoaSetApplicationBundleDir() { - extern std::array _searchpaths; + extern EnumClassIndexContainer, Searchpath> _searchpaths; char tmp[MAXPATHLEN]; CFAutoRelease url(CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle())); if (CFURLGetFileSystemRepresentation(url.get(), true, (unsigned char *)tmp, MAXPATHLEN)) { - _searchpaths[SP_APPLICATION_BUNDLE_DIR] = tmp; - AppendPathSeparator(_searchpaths[SP_APPLICATION_BUNDLE_DIR]); + _searchpaths[Searchpath::ApplicationBundleDir] = tmp; + AppendPathSeparator(_searchpaths[Searchpath::ApplicationBundleDir]); } else { - _searchpaths[SP_APPLICATION_BUNDLE_DIR].clear(); + _searchpaths[Searchpath::ApplicationBundleDir].clear(); } } diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index bebc214c69..0d2891836e 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -248,7 +248,7 @@ extern std::string _config_file; void DetermineBasePaths(std::string_view exe) { - extern std::array _searchpaths; + extern EnumClassIndexContainer, Searchpath> _searchpaths; wchar_t path[MAX_PATH]; #ifdef WITH_PERSONAL_DIR @@ -257,13 +257,13 @@ void DetermineBasePaths(std::string_view exe) AppendPathSeparator(tmp); tmp += PERSONAL_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_PERSONAL_DIR] = tmp; + _searchpaths[Searchpath::PersonalDir] = tmp; tmp += "content_download"; AppendPathSeparator(tmp); - _searchpaths[SP_AUTODOWNLOAD_PERSONAL_DIR] = tmp; + _searchpaths[Searchpath::AutodownloadPersonalDir] = tmp; } else { - _searchpaths[SP_PERSONAL_DIR].clear(); + _searchpaths[Searchpath::PersonalDir].clear(); } if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_COMMON_DOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, path))) { @@ -271,13 +271,13 @@ void DetermineBasePaths(std::string_view exe) AppendPathSeparator(tmp); tmp += PERSONAL_DIR; AppendPathSeparator(tmp); - _searchpaths[SP_SHARED_DIR] = tmp; + _searchpaths[Searchpath::SharedDir] = tmp; } else { - _searchpaths[SP_SHARED_DIR].clear(); + _searchpaths[Searchpath::SharedDir].clear(); } #else - _searchpaths[SP_PERSONAL_DIR].clear(); - _searchpaths[SP_SHARED_DIR].clear(); + _searchpaths[Searchpath::PersonalDir].clear(); + _searchpaths[Searchpath::SharedDir].clear(); #endif if (_config_file.empty()) { @@ -285,43 +285,43 @@ void DetermineBasePaths(std::string_view exe) getcwd(cwd, lengthof(cwd)); std::string cwd_s(cwd); AppendPathSeparator(cwd_s); - _searchpaths[SP_WORKING_DIR] = cwd_s; + _searchpaths[Searchpath::WorkingDir] = cwd_s; } else { /* Use the folder of the config file as working directory. */ wchar_t config_dir[MAX_PATH]; convert_to_fs(_config_file, path); if (!GetFullPathName(path, static_cast(std::size(config_dir)), config_dir, nullptr)) { Debug(misc, 0, "GetFullPathName failed ({})", GetLastError()); - _searchpaths[SP_WORKING_DIR].clear(); + _searchpaths[Searchpath::WorkingDir].clear(); } else { std::string tmp(FS2OTTD(config_dir)); auto pos = tmp.find_last_of(PATHSEPCHAR); if (pos != std::string::npos) tmp.erase(pos + 1); - _searchpaths[SP_WORKING_DIR] = tmp; + _searchpaths[Searchpath::WorkingDir] = tmp; } } if (!GetModuleFileName(nullptr, path, static_cast(std::size(path)))) { Debug(misc, 0, "GetModuleFileName failed ({})", GetLastError()); - _searchpaths[SP_BINARY_DIR].clear(); + _searchpaths[Searchpath::BinaryDir].clear(); } else { wchar_t exec_dir[MAX_PATH]; convert_to_fs(exe, path); if (!GetFullPathName(path, static_cast(std::size(exec_dir)), exec_dir, nullptr)) { Debug(misc, 0, "GetFullPathName failed ({})", GetLastError()); - _searchpaths[SP_BINARY_DIR].clear(); + _searchpaths[Searchpath::BinaryDir].clear(); } else { std::string tmp(FS2OTTD(exec_dir)); auto pos = tmp.find_last_of(PATHSEPCHAR); if (pos != std::string::npos) tmp.erase(pos + 1); - _searchpaths[SP_BINARY_DIR] = tmp; + _searchpaths[Searchpath::BinaryDir] = tmp; } } - _searchpaths[SP_INSTALLATION_DIR].clear(); - _searchpaths[SP_APPLICATION_BUNDLE_DIR].clear(); + _searchpaths[Searchpath::InstallationDir].clear(); + _searchpaths[Searchpath::ApplicationBundleDir].clear(); }