From 26db4ccf09f4615747aa92942f05cadb12edbb07 Mon Sep 17 00:00:00 2001 From: frosch Date: Fri, 18 Apr 2025 15:20:55 +0200 Subject: [PATCH] Codechange: Turn bit-stuffed FiosType enum into a struct. (#14019) --- src/console_cmds.cpp | 14 ++++---- src/fileio_type.h | 60 +++++++++------------------------- src/fios.cpp | 20 ++++-------- src/fios_gui.cpp | 12 +++---- src/genworld_gui.cpp | 2 +- src/landscape.cpp | 2 +- src/network/network_client.cpp | 2 +- src/network/network_server.cpp | 2 +- src/openttd.cpp | 18 +++++----- src/saveload/afterload.cpp | 2 +- src/saveload/saveload.cpp | 22 +++---------- src/saveload/saveload.h | 6 ++-- src/saveload/signs_sl.cpp | 2 +- 13 files changed, 59 insertions(+), 105 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index cb091832ff..948f1c0aef 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -462,7 +462,7 @@ DEF_CONSOLE_CMD(ConLoad) _console_file_list_savegame.ValidateFileList(); const FiosItem *item = _console_file_list_savegame.FindItem(file); if (item != nullptr) { - if (GetAbstractFileType(item->type) == FT_SAVEGAME) { + if (item->type.abstract == FT_SAVEGAME) { _switch_mode = SM_LOAD_GAME; _file_to_saveload.Set(*item); } else { @@ -488,7 +488,7 @@ DEF_CONSOLE_CMD(ConLoadScenario) _console_file_list_scenario.ValidateFileList(); const FiosItem *item = _console_file_list_scenario.FindItem(file); if (item != nullptr) { - if (GetAbstractFileType(item->type) == FT_SCENARIO) { + if (item->type.abstract == FT_SCENARIO) { _switch_mode = SM_LOAD_GAME; _file_to_saveload.Set(*item); } else { @@ -514,7 +514,7 @@ DEF_CONSOLE_CMD(ConLoadHeightmap) _console_file_list_heightmap.ValidateFileList(); const FiosItem *item = _console_file_list_heightmap.FindItem(file); if (item != nullptr) { - if (GetAbstractFileType(item->type) == FT_HEIGHTMAP) { + if (item->type.abstract == FT_HEIGHTMAP) { _switch_mode = SM_START_HEIGHTMAP; _file_to_saveload.Set(*item); } else { @@ -614,8 +614,10 @@ DEF_CONSOLE_CMD(ConChangeDirectory) _console_file_list_savegame.ValidateFileList(true); const FiosItem *item = _console_file_list_savegame.FindItem(file); if (item != nullptr) { - switch (item->type) { - case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT: + switch (item->type.detailed) { + case DFT_FIOS_DIR: + case DFT_FIOS_DRIVE: + case DFT_FIOS_PARENT: FiosBrowseTo(item); break; default: IConsolePrint(CC_ERROR, "{}: Not a directory.", file); @@ -1307,7 +1309,7 @@ DEF_CONSOLE_CMD(ConReload) return true; } - if (_file_to_saveload.abstract_ftype == FT_NONE || _file_to_saveload.abstract_ftype == FT_INVALID) { + if (_file_to_saveload.ftype.abstract == FT_NONE || _file_to_saveload.ftype.abstract == FT_INVALID) { IConsolePrint(CC_ERROR, "No game loaded to reload."); return true; } diff --git a/src/fileio_type.h b/src/fileio_type.h index 46d1fbfdca..54e47aeff4 100644 --- a/src/fileio_type.h +++ b/src/fileio_type.h @@ -21,8 +21,6 @@ enum AbstractFileType : uint8_t { FT_TOWN_DATA, ///< town data file FT_INVALID = 7, ///< Invalid or unknown file type. - FT_NUMBITS = 3, ///< Number of bits required for storing a #AbstractFileType value. - FT_MASK = (1 << FT_NUMBITS) - 1, ///< Bitmask for extracting an abstract file type. }; /** Kinds of files in each #AbstractFileType. */ @@ -58,56 +56,30 @@ enum SaveLoadOperation : uint8_t { SLO_INVALID, ///< Unknown file operation. }; -/** - * Construct an enum value for #FiosType as a combination of an abstract and a detailed file type. - * @param abstract Abstract file type (one of #AbstractFileType). - * @param detailed Detailed file type (one of #DetailedFileType). - */ -#define MAKE_FIOS_TYPE(abstract, detailed) ((abstract) | ((detailed) << FT_NUMBITS)) - /** * Elements of a file system that are recognized. - * Values are a combination of #AbstractFileType and #DetailedFileType. - * @see GetAbstractFileType GetDetailedFileType */ -enum FiosType : uint16_t { - FIOS_TYPE_DRIVE = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DRIVE), - FIOS_TYPE_PARENT = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_PARENT), - FIOS_TYPE_DIR = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DIR), - FIOS_TYPE_DIRECT = MAKE_FIOS_TYPE(FT_NONE, DFT_FIOS_DIRECT), +struct FiosType { + AbstractFileType abstract; ///< Abstract file type. + DetailedFileType detailed; ///< Detailed file type. - FIOS_TYPE_FILE = MAKE_FIOS_TYPE(FT_SAVEGAME, DFT_GAME_FILE), - FIOS_TYPE_OLDFILE = MAKE_FIOS_TYPE(FT_SAVEGAME, DFT_OLD_GAME_FILE), - FIOS_TYPE_SCENARIO = MAKE_FIOS_TYPE(FT_SCENARIO, DFT_GAME_FILE), - FIOS_TYPE_OLD_SCENARIO = MAKE_FIOS_TYPE(FT_SCENARIO, DFT_OLD_GAME_FILE), - FIOS_TYPE_PNG = MAKE_FIOS_TYPE(FT_HEIGHTMAP, DFT_HEIGHTMAP_PNG), - FIOS_TYPE_BMP = MAKE_FIOS_TYPE(FT_HEIGHTMAP, DFT_HEIGHTMAP_BMP), - FIOS_TYPE_JSON = MAKE_FIOS_TYPE(FT_TOWN_DATA, DFT_TOWN_DATA_JSON), - - FIOS_TYPE_INVALID = MAKE_FIOS_TYPE(FT_INVALID, DFT_INVALID), + constexpr bool operator==(const FiosType &) const noexcept = default; }; -#undef MAKE_FIOS_TYPE +constexpr FiosType FIOS_TYPE_DRIVE{FT_NONE, DFT_FIOS_DRIVE}; +constexpr FiosType FIOS_TYPE_PARENT{FT_NONE, DFT_FIOS_PARENT}; +constexpr FiosType FIOS_TYPE_DIR{FT_NONE, DFT_FIOS_DIR}; +constexpr FiosType FIOS_TYPE_DIRECT{FT_NONE, DFT_FIOS_DIRECT}; -/** - * Extract the abstract file type from a #FiosType. - * @param fios_type Type to query. - * @return The Abstract file type of the \a fios_type. - */ -inline AbstractFileType GetAbstractFileType(FiosType fios_type) -{ - return static_cast(static_cast(fios_type) & FT_MASK); -} +constexpr FiosType FIOS_TYPE_FILE{FT_SAVEGAME, DFT_GAME_FILE}; +constexpr FiosType FIOS_TYPE_OLDFILE{FT_SAVEGAME, DFT_OLD_GAME_FILE}; +constexpr FiosType FIOS_TYPE_SCENARIO{FT_SCENARIO, DFT_GAME_FILE}; +constexpr FiosType FIOS_TYPE_OLD_SCENARIO{FT_SCENARIO, DFT_OLD_GAME_FILE}; +constexpr FiosType FIOS_TYPE_PNG{FT_HEIGHTMAP, DFT_HEIGHTMAP_PNG}; +constexpr FiosType FIOS_TYPE_BMP{FT_HEIGHTMAP, DFT_HEIGHTMAP_BMP}; +constexpr FiosType FIOS_TYPE_JSON{FT_TOWN_DATA, DFT_TOWN_DATA_JSON}; -/** - * Extract the detailed file type from a #FiosType. - * @param fios_type Type to query. - * @return The Detailed file type of the \a fios_type. - */ -inline DetailedFileType GetDetailedFileType(FiosType fios_type) -{ - return static_cast(fios_type >> FT_NUMBITS); -} +constexpr FiosType FIOS_TYPE_INVALID{FT_INVALID, DFT_INVALID}; /** * The different kinds of subdirectories OpenTTD uses diff --git a/src/fios.cpp b/src/fios.cpp index 9206aa101a..4e74c2e246 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -142,18 +142,18 @@ std::string FiosGetCurrentPath() */ bool FiosBrowseTo(const FiosItem *item) { - switch (item->type) { - case FIOS_TYPE_DRIVE: + switch (item->type.detailed) { + case DFT_FIOS_DRIVE: #if defined(_WIN32) assert(_fios_path != nullptr); *_fios_path = std::string{ item->title, 0, 1 } + ":" PATHSEP; #endif break; - case FIOS_TYPE_INVALID: + case DFT_INVALID: break; - case FIOS_TYPE_PARENT: { + case DFT_FIOS_PARENT: { assert(_fios_path != nullptr); auto s = _fios_path->find_last_of(PATHSEPCHAR); if (s != std::string::npos && s != 0) { @@ -167,24 +167,18 @@ bool FiosBrowseTo(const FiosItem *item) break; } - case FIOS_TYPE_DIR: + case DFT_FIOS_DIR: assert(_fios_path != nullptr); *_fios_path += item->name; *_fios_path += PATHSEP; break; - case FIOS_TYPE_DIRECT: + case DFT_FIOS_DIRECT: assert(_fios_path != nullptr); *_fios_path = item->name; break; - case FIOS_TYPE_FILE: - case FIOS_TYPE_OLDFILE: - case FIOS_TYPE_SCENARIO: - case FIOS_TYPE_OLD_SCENARIO: - case FIOS_TYPE_PNG: - case FIOS_TYPE_BMP: - case FIOS_TYPE_JSON: + default: return false; } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index e3ff376497..6bf9210eee 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -309,10 +309,10 @@ static void SortSaveGameList(FileList &file_list) * Only sort savegames/scenarios, not directories */ for (const auto &item : file_list) { - switch (item.type) { - case FIOS_TYPE_DIR: sort_start++; break; - case FIOS_TYPE_PARENT: sort_start++; break; - case FIOS_TYPE_DRIVE: sort_end++; break; + switch (item.type.detailed) { + case DFT_FIOS_DIR: sort_start++; break; + case DFT_FIOS_PARENT: sort_start++; break; + case DFT_FIOS_DRIVE: sort_end++; break; default: break; } } @@ -514,7 +514,7 @@ public: } else if (item == this->highlighted) { GfxFillRect(br.left, tr.top, br.right, tr.bottom, PC_VERY_DARK_BLUE); } - DrawString(tr, item->title, _fios_colours[GetDetailedFileType(item->type)]); + DrawString(tr, item->title, _fios_colours[item->type.detailed]); tr = tr.Translate(0, this->resize.step_height); } break; @@ -719,7 +719,7 @@ public: this->selected = file; _load_check_data.Clear(); - if (GetDetailedFileType(file->type) == DFT_GAME_FILE) { + if (file->type.detailed == DFT_GAME_FILE) { /* Other detailed file types cannot be checked before. */ SaveOrLoad(file->name, SLO_CHECK, DFT_GAME_FILE, NO_DIRECTORY, false); } diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index a646638cff..854ae3d226 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -997,7 +997,7 @@ static void _ShowGenerateLandscape(GenerateLandscapeWindowMode mode) if (mode == GLWM_HEIGHTMAP) { /* If the function returns negative, it means there was a problem loading the heightmap */ - if (!GetHeightmapDimensions(_file_to_saveload.detail_ftype, _file_to_saveload.name.c_str(), &x, &y)) return; + if (!GetHeightmapDimensions(_file_to_saveload.ftype.detailed, _file_to_saveload.name.c_str(), &x, &y)) return; } WindowDesc &desc = (mode == GLWM_HEIGHTMAP) ? _heightmap_load_desc : _generate_landscape_desc; diff --git a/src/landscape.cpp b/src/landscape.cpp index 702889a922..02a61ddfc0 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -1543,7 +1543,7 @@ bool GenerateLandscape(uint8_t mode) if (mode == GWM_HEIGHTMAP) { SetGeneratingWorldProgress(GWP_LANDSCAPE, steps + GLS_HEIGHTMAP); - if (!LoadHeightmap(_file_to_saveload.detail_ftype, _file_to_saveload.name.c_str())) { + if (!LoadHeightmap(_file_to_saveload.ftype.detailed, _file_to_saveload.name.c_str())) { return false; } IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 928b01f828..c662f9f6d3 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -823,7 +823,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet ClearErrorMessages(); /* Set the abstract filetype. This is read during savegame load. */ - _file_to_saveload.SetMode(SLO_LOAD, FT_SAVEGAME, DFT_GAME_FILE); + _file_to_saveload.SetMode(FIOS_TYPE_FILE, SLO_LOAD); bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, this->savegame); this->savegame = nullptr; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 6247807a39..5eb29ad2a0 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1814,7 +1814,7 @@ void NetworkServer_Tick(bool send_frame) static void NetworkRestartMap() { _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED; - switch (_file_to_saveload.abstract_ftype) { + switch (_file_to_saveload.ftype.abstract) { case FT_SAVEGAME: case FT_SCENARIO: _switch_mode = SM_LOAD_GAME; diff --git a/src/openttd.cpp b/src/openttd.cpp index 6d5dd18ad9..d095f23b01 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -579,14 +579,14 @@ int openttd_main(std::span arguments) } /* Allow for '-e' before or after '-g'. */ - switch (GetAbstractFileType(ft)) { + switch (ft.abstract) { case FT_SAVEGAME: _switch_mode = (_switch_mode == SM_EDITOR ? SM_LOAD_SCENARIO : SM_LOAD_GAME); break; case FT_SCENARIO: _switch_mode = (_switch_mode == SM_EDITOR ? SM_LOAD_SCENARIO : SM_LOAD_GAME); break; case FT_HEIGHTMAP: _switch_mode = (_switch_mode == SM_EDITOR ? SM_LOAD_HEIGHTMAP : SM_START_HEIGHTMAP); break; default: break; } - _file_to_saveload.SetMode(SLO_LOAD, GetAbstractFileType(ft), GetDetailedFileType(ft)); + _file_to_saveload.SetMode(ft, SLO_LOAD); break; } @@ -886,7 +886,7 @@ static void MakeNewGame(bool from_heightmap, bool reset_settings) _game_mode = GM_NORMAL; if (!from_heightmap) { /* "reload" command needs to know what mode we were in. */ - _file_to_saveload.SetMode(SLO_INVALID, FT_INVALID, DFT_INVALID); + _file_to_saveload.SetMode(FIOS_TYPE_INVALID, SLO_INVALID); } ResetGRFConfig(true); @@ -904,7 +904,7 @@ static void MakeNewEditorWorld() { _game_mode = GM_EDITOR; /* "reload" command needs to know what mode we were in. */ - _file_to_saveload.SetMode(SLO_INVALID, FT_INVALID, DFT_INVALID); + _file_to_saveload.SetMode(FIOS_TYPE_INVALID, SLO_INVALID); ResetGRFConfig(true); @@ -1054,12 +1054,12 @@ void SwitchToMode(SwitchMode new_mode) break; case SM_RELOADGAME: // Reload with what-ever started the game - if (_file_to_saveload.abstract_ftype == FT_SAVEGAME || _file_to_saveload.abstract_ftype == FT_SCENARIO) { + if (_file_to_saveload.ftype.abstract == FT_SAVEGAME || _file_to_saveload.ftype.abstract == FT_SCENARIO) { /* Reload current savegame/scenario */ _switch_mode = _game_mode == GM_EDITOR ? SM_LOAD_SCENARIO : SM_LOAD_GAME; SwitchToMode(_switch_mode); break; - } else if (_file_to_saveload.abstract_ftype == FT_HEIGHTMAP) { + } else if (_file_to_saveload.ftype.abstract == FT_HEIGHTMAP) { /* Restart current heightmap */ _switch_mode = _game_mode == GM_EDITOR ? SM_LOAD_HEIGHTMAP : SM_RESTART_HEIGHTMAP; SwitchToMode(_switch_mode); @@ -1084,10 +1084,10 @@ void SwitchToMode(SwitchMode new_mode) ResetGRFConfig(true); ResetWindowSystem(); - if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, NO_DIRECTORY)) { + if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.ftype.detailed, GM_NORMAL, NO_DIRECTORY)) { ShowErrorMessage(GetSaveLoadErrorType(), GetSaveLoadErrorMessage(), WL_CRITICAL); } else { - if (_file_to_saveload.abstract_ftype == FT_SCENARIO) { + if (_file_to_saveload.ftype.abstract == FT_SCENARIO) { OnStartScenario(); } OnStartGame(_network_dedicated); @@ -1120,7 +1120,7 @@ void SwitchToMode(SwitchMode new_mode) break; case SM_LOAD_SCENARIO: { // Load scenario from scenario editor - if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_EDITOR, NO_DIRECTORY)) { + if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.ftype.detailed, GM_EDITOR, NO_DIRECTORY)) { SetLocalCompany(OWNER_NONE); GenerateSavegameId(); _settings_newgame.game_creation.starting_year = TimerGameCalendar::year; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 23de2d9de1..9fca094948 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -256,7 +256,7 @@ static void InitializeWindowsAndCaches() /* For each company, verify (while loading a scenario) that the inauguration date is the current year and set it * accordingly if it is not the case. No need to set it on companies that are not been used already, * thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */ - if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != EconomyTime::MIN_YEAR) { + if (_file_to_saveload.ftype.abstract == FT_SCENARIO && c->inaugurated_year != EconomyTime::MIN_YEAR) { c->inaugurated_year = TimerGameEconomy::year; } } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9c7bcc32c6..d6f2536f67 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -3370,33 +3370,21 @@ std::string GenerateDefaultSaveName() return filename; } -/** - * Set the mode and file type of the file to save or load based on the type of file entry at the file system. - * @param ft Type of file entry of the file system. - */ -void FileToSaveLoad::SetMode(FiosType ft) -{ - this->SetMode(SLO_LOAD, GetAbstractFileType(ft), GetDetailedFileType(ft)); -} - /** * Set the mode and file type of the file to save or load. + * @param ft File type. * @param fop File operation being performed. - * @param aft Abstract file type. - * @param dft Detailed file type. */ -void FileToSaveLoad::SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft) +void FileToSaveLoad::SetMode(const FiosType &ft, SaveLoadOperation fop) { - if (aft == FT_INVALID || aft == FT_NONE) { + if (ft.abstract == FT_INVALID || ft.abstract == FT_NONE) { this->file_op = SLO_INVALID; - this->detail_ftype = DFT_INVALID; - this->abstract_ftype = FT_INVALID; + this->ftype = FIOS_TYPE_INVALID; return; } this->file_op = fop; - this->detail_ftype = dft; - this->abstract_ftype = aft; + this->ftype = ft; } /** diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index b665661d7d..246088625e 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -414,13 +414,11 @@ enum SaveOrLoadResult : uint8_t { /** Deals with the type of the savegame, independent of extension */ struct FileToSaveLoad { SaveLoadOperation file_op; ///< File operation to perform. - DetailedFileType detail_ftype; ///< Concrete file type (PNG, BMP, old save, etc). - AbstractFileType abstract_ftype; ///< Abstract type of file (scenario, heightmap, etc). + FiosType ftype; ///< File type. std::string name; ///< Name of the file. std::string title; ///< Internal name of the game. - void SetMode(FiosType ft); - void SetMode(SaveLoadOperation fop, AbstractFileType aft, DetailedFileType dft); + void SetMode(const FiosType &ft, SaveLoadOperation fop = SLO_LOAD); void Set(const FiosItem &item); }; diff --git a/src/saveload/signs_sl.cpp b/src/saveload/signs_sl.cpp index 698bd9f176..e8c1061374 100644 --- a/src/saveload/signs_sl.cpp +++ b/src/saveload/signs_sl.cpp @@ -62,7 +62,7 @@ struct SIGNChunkHandler : ChunkHandler { } /* Signs placed in scenario editor shall now be OWNER_DEITY */ - if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) { + if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.ftype.abstract == FT_SCENARIO) { si->owner = OWNER_DEITY; } }