Codechange: make Searchpath a scoped enum

This commit is contained in:
Peter Nelson
2026-04-05 19:55:59 +01:00
committed by Peter Nelson
parent 5aae8e2d64
commit 78bc829886
7 changed files with 81 additions and 81 deletions
+45 -45
View File
@@ -62,7 +62,7 @@ static const EnumClassIndexContainer<std::array<std::string_view, to_underlying(
* An empty string tells that there is no such path for the
* current operating system.
*/
std::array<std::string, NUM_SEARCHPATHS> _searchpaths;
EnumClassIndexContainer<std::array<std::string, to_underlying(Searchpath::End)>, Searchpath> _searchpaths;
std::vector<Searchpath> _valid_searchpaths;
/** List of tar files found in each subdirectory. */
EnumClassIndexContainer<std::array<TarList, to_underlying(Subdirectory::End)>, Subdirectory> _tar_list;
@@ -76,7 +76,7 @@ EnumClassIndexContainer<std::array<TarFileList, to_underlying(Subdirectory::End)
*/
static bool IsValidSearchPath(Searchpath sp)
{
return sp < _searchpaths.size() && !_searchpaths[sp].empty();
return to_underlying(sp) < _searchpaths.size() && !_searchpaths[sp].empty();
}
static void FillValidSearchPaths(bool only_local_path)
@@ -84,14 +84,14 @@ static void FillValidSearchPaths(bool only_local_path)
_valid_searchpaths.clear();
std::set<std::string> 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);
+13 -13
View File
@@ -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)
+1 -1
View File
@@ -48,7 +48,7 @@ static constexpr size_t CHANGELOG_VERSIONS_LIMIT = 20;
static std::optional<std::string> 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) {
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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";
+4 -4
View File
@@ -126,15 +126,15 @@ std::optional<std::string> GetClipboardContents()
*/
void CocoaSetApplicationBundleDir()
{
extern std::array<std::string, NUM_SEARCHPATHS> _searchpaths;
extern EnumClassIndexContainer<std::array<std::string, to_underlying(Searchpath::End)>, Searchpath> _searchpaths;
char tmp[MAXPATHLEN];
CFAutoRelease<CFURLRef> 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();
}
}
+16 -16
View File
@@ -248,7 +248,7 @@ extern std::string _config_file;
void DetermineBasePaths(std::string_view exe)
{
extern std::array<std::string, NUM_SEARCHPATHS> _searchpaths;
extern EnumClassIndexContainer<std::array<std::string, to_underlying(Searchpath::End)>, 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<DWORD>(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<DWORD>(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<DWORD>(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();
}