diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -214,86 +214,92 @@ struct SaveLoadParams { static SaveLoadParams _sl; ///< Parameters used for/at saveload. -/* these define the chunks */ -extern const ChunkHandler _gamelog_chunk_handlers[]; -extern const ChunkHandler _map_chunk_handlers[]; -extern const ChunkHandler _misc_chunk_handlers[]; -extern const ChunkHandler _name_chunk_handlers[]; -extern const ChunkHandler _cheat_chunk_handlers[] ; -extern const ChunkHandler _setting_chunk_handlers[]; -extern const ChunkHandler _company_chunk_handlers[]; -extern const ChunkHandler _engine_chunk_handlers[]; -extern const ChunkHandler _veh_chunk_handlers[]; -extern const ChunkHandler _waypoint_chunk_handlers[]; -extern const ChunkHandler _depot_chunk_handlers[]; -extern const ChunkHandler _order_chunk_handlers[]; -extern const ChunkHandler _town_chunk_handlers[]; -extern const ChunkHandler _sign_chunk_handlers[]; -extern const ChunkHandler _station_chunk_handlers[]; -extern const ChunkHandler _industry_chunk_handlers[]; -extern const ChunkHandler _economy_chunk_handlers[]; -extern const ChunkHandler _subsidy_chunk_handlers[]; -extern const ChunkHandler _cargomonitor_chunk_handlers[]; -extern const ChunkHandler _goal_chunk_handlers[]; -extern const ChunkHandler _story_page_chunk_handlers[]; -extern const ChunkHandler _ai_chunk_handlers[]; -extern const ChunkHandler _game_chunk_handlers[]; -extern const ChunkHandler _animated_tile_chunk_handlers[]; -extern const ChunkHandler _newgrf_chunk_handlers[]; -extern const ChunkHandler _group_chunk_handlers[]; -extern const ChunkHandler _cargopacket_chunk_handlers[]; -extern const ChunkHandler _autoreplace_chunk_handlers[]; -extern const ChunkHandler _labelmaps_chunk_handlers[]; -extern const ChunkHandler _linkgraph_chunk_handlers[]; -extern const ChunkHandler _airport_chunk_handlers[]; -extern const ChunkHandler _object_chunk_handlers[]; -extern const ChunkHandler _persistent_storage_chunk_handlers[]; - -/** Array of all chunks in a savegame, \c nullptr terminated. */ -static const ChunkHandler * const _chunk_handlers[] = { - _gamelog_chunk_handlers, - _map_chunk_handlers, - _misc_chunk_handlers, - _name_chunk_handlers, - _cheat_chunk_handlers, - _setting_chunk_handlers, - _veh_chunk_handlers, - _waypoint_chunk_handlers, - _depot_chunk_handlers, - _order_chunk_handlers, - _industry_chunk_handlers, - _economy_chunk_handlers, - _subsidy_chunk_handlers, - _cargomonitor_chunk_handlers, - _goal_chunk_handlers, - _story_page_chunk_handlers, - _engine_chunk_handlers, - _town_chunk_handlers, - _sign_chunk_handlers, - _station_chunk_handlers, - _company_chunk_handlers, - _ai_chunk_handlers, - _game_chunk_handlers, - _animated_tile_chunk_handlers, - _newgrf_chunk_handlers, - _group_chunk_handlers, - _cargopacket_chunk_handlers, - _autoreplace_chunk_handlers, - _labelmaps_chunk_handlers, - _linkgraph_chunk_handlers, - _airport_chunk_handlers, - _object_chunk_handlers, - _persistent_storage_chunk_handlers, - nullptr, -}; - -/** - * Iterate over all chunk handlers. - * @param ch the chunk handler iterator - */ -#define FOR_ALL_CHUNK_HANDLERS(ch) \ - for (const ChunkHandler * const *chsc = _chunk_handlers; *chsc != nullptr; chsc++) \ - for (const ChunkHandler *ch = *chsc; ch != nullptr; ch = (ch->flags & CH_LAST) ? nullptr : ch + 1) +static const std::vector &ChunkHandlers() +{ + /* These define the chunks */ + extern const ChunkHandlerTable _gamelog_chunk_handlers; + extern const ChunkHandlerTable _map_chunk_handlers; + extern const ChunkHandlerTable _misc_chunk_handlers; + extern const ChunkHandlerTable _name_chunk_handlers; + extern const ChunkHandlerTable _cheat_chunk_handlers; + extern const ChunkHandlerTable _setting_chunk_handlers; + extern const ChunkHandlerTable _company_chunk_handlers; + extern const ChunkHandlerTable _engine_chunk_handlers; + extern const ChunkHandlerTable _veh_chunk_handlers; + extern const ChunkHandlerTable _waypoint_chunk_handlers; + extern const ChunkHandlerTable _depot_chunk_handlers; + extern const ChunkHandlerTable _order_chunk_handlers; + extern const ChunkHandlerTable _town_chunk_handlers; + extern const ChunkHandlerTable _sign_chunk_handlers; + extern const ChunkHandlerTable _station_chunk_handlers; + extern const ChunkHandlerTable _industry_chunk_handlers; + extern const ChunkHandlerTable _economy_chunk_handlers; + extern const ChunkHandlerTable _subsidy_chunk_handlers; + extern const ChunkHandlerTable _cargomonitor_chunk_handlers; + extern const ChunkHandlerTable _goal_chunk_handlers; + extern const ChunkHandlerTable _story_page_chunk_handlers; + extern const ChunkHandlerTable _ai_chunk_handlers; + extern const ChunkHandlerTable _game_chunk_handlers; + extern const ChunkHandlerTable _animated_tile_chunk_handlers; + extern const ChunkHandlerTable _newgrf_chunk_handlers; + extern const ChunkHandlerTable _group_chunk_handlers; + extern const ChunkHandlerTable _cargopacket_chunk_handlers; + extern const ChunkHandlerTable _autoreplace_chunk_handlers; + extern const ChunkHandlerTable _labelmaps_chunk_handlers; + extern const ChunkHandlerTable _linkgraph_chunk_handlers; + extern const ChunkHandlerTable _airport_chunk_handlers; + extern const ChunkHandlerTable _object_chunk_handlers; + extern const ChunkHandlerTable _persistent_storage_chunk_handlers; + + /** List of all chunks in a savegame. */ + static const ChunkHandlerTable _chunk_handler_tables[] = { + _gamelog_chunk_handlers, + _map_chunk_handlers, + _misc_chunk_handlers, + _name_chunk_handlers, + _cheat_chunk_handlers, + _setting_chunk_handlers, + _veh_chunk_handlers, + _waypoint_chunk_handlers, + _depot_chunk_handlers, + _order_chunk_handlers, + _industry_chunk_handlers, + _economy_chunk_handlers, + _subsidy_chunk_handlers, + _cargomonitor_chunk_handlers, + _goal_chunk_handlers, + _story_page_chunk_handlers, + _engine_chunk_handlers, + _town_chunk_handlers, + _sign_chunk_handlers, + _station_chunk_handlers, + _company_chunk_handlers, + _ai_chunk_handlers, + _game_chunk_handlers, + _animated_tile_chunk_handlers, + _newgrf_chunk_handlers, + _group_chunk_handlers, + _cargopacket_chunk_handlers, + _autoreplace_chunk_handlers, + _labelmaps_chunk_handlers, + _linkgraph_chunk_handlers, + _airport_chunk_handlers, + _object_chunk_handlers, + _persistent_storage_chunk_handlers, + }; + + static std::vector _chunk_handlers; + + if (_chunk_handlers.empty()) { + for (auto &chunk_handler_table : _chunk_handler_tables) { + for (auto &chunk_handler : chunk_handler_table) { + _chunk_handlers.push_back(chunk_handler); + } + } + } + + return _chunk_handlers; +} /** Null all pointers (convert index -> nullptr) */ static void SlNullPointers() @@ -305,10 +311,10 @@ static void SlNullPointers() * pointers from other pools. */ _sl_version = SAVEGAME_VERSION; - FOR_ALL_CHUNK_HANDLERS(ch) { - if (ch->ptrs_proc != nullptr) { - DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); - ch->ptrs_proc(); + for (auto &ch : ChunkHandlers()) { + if (ch.ptrs_proc != nullptr) { + DEBUG(sl, 3, "Nulling pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + ch.ptrs_proc(); } } @@ -1654,7 +1660,7 @@ void SlAutolength(AutolengthProc *proc, * Load a chunk of data (eg vehicles, stations, etc.) * @param ch The chunkhandler that will be used for the operation */ -static void SlLoadChunk(const ChunkHandler *ch) +static void SlLoadChunk(const ChunkHandler &ch) { byte m = SlReadByte(); size_t len; @@ -1666,11 +1672,11 @@ static void SlLoadChunk(const ChunkHandl switch (m) { case CH_ARRAY: _sl.array_index = 0; - ch->load_proc(); + ch.load_proc(); if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); break; case CH_SPARSE_ARRAY: - ch->load_proc(); + ch.load_proc(); if (_next_offs != 0) SlErrorCorrupt("Invalid array length"); break; default: @@ -1680,7 +1686,7 @@ static void SlLoadChunk(const ChunkHandl len += SlReadUint16(); _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; - ch->load_proc(); + ch.load_proc(); if (_sl.reader->GetSize() != endoffs) SlErrorCorrupt("Invalid chunk size"); } else { SlErrorCorrupt("Invalid chunk type"); @@ -1694,7 +1700,7 @@ static void SlLoadChunk(const ChunkHandl * If the chunkhandler is nullptr, the chunk is skipped. * @param ch The chunkhandler that will be used for the operation */ -static void SlLoadCheckChunk(const ChunkHandler *ch) +static void SlLoadCheckChunk(const ChunkHandler &ch) { byte m = SlReadByte(); size_t len; @@ -1706,15 +1712,15 @@ static void SlLoadCheckChunk(const Chunk switch (m) { case CH_ARRAY: _sl.array_index = 0; - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipArray(); } break; case CH_SPARSE_ARRAY: - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipArray(); } @@ -1726,8 +1732,8 @@ static void SlLoadCheckChunk(const Chunk len += SlReadUint16(); _sl.obj_len = len; endoffs = _sl.reader->GetSize() + len; - if (ch->load_check_proc) { - ch->load_check_proc(); + if (ch.load_check_proc) { + ch.load_check_proc(); } else { SlSkipBytes(len); } @@ -1744,18 +1750,18 @@ static void SlLoadCheckChunk(const Chunk * prefixed by an ID identifying it, followed by data, and terminator where appropriate * @param ch The chunkhandler that will be used for the operation */ -static void SlSaveChunk(const ChunkHandler *ch) +static void SlSaveChunk(const ChunkHandler &ch) { - ChunkSaveLoadProc *proc = ch->save_proc; + ChunkSaveLoadProc *proc = ch.save_proc; /* Don't save any chunk information if there is no save handler. */ if (proc == nullptr) return; - SlWriteUint32(ch->id); - DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); - - _sl.block_mode = ch->flags & CH_TYPE_MASK; - switch (ch->flags & CH_TYPE_MASK) { + SlWriteUint32(ch.id); + DEBUG(sl, 2, "Saving chunk %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + + _sl.block_mode = ch.type; + switch (ch.type) { case CH_RIFF: _sl.need_length = NL_WANTLENGTH; proc(); @@ -1778,7 +1784,7 @@ static void SlSaveChunk(const ChunkHandl /** Save all chunks */ static void SlSaveChunks() { - FOR_ALL_CHUNK_HANDLERS(ch) { + for (auto &ch : ChunkHandlers()) { SlSaveChunk(ch); } @@ -1794,7 +1800,7 @@ static void SlSaveChunks() */ static const ChunkHandler *SlFindChunkHandler(uint32 id) { - FOR_ALL_CHUNK_HANDLERS(ch) if (ch->id == id) return ch; + for (auto &ch : ChunkHandlers()) if (ch.id == id) return &ch; return nullptr; } @@ -1809,7 +1815,7 @@ static void SlLoadChunks() ch = SlFindChunkHandler(id); if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); - SlLoadChunk(ch); + SlLoadChunk(*ch); } } @@ -1824,7 +1830,7 @@ static void SlLoadCheckChunks() ch = SlFindChunkHandler(id); if (ch == nullptr) SlErrorCorrupt("Unknown chunk type"); - SlLoadCheckChunk(ch); + SlLoadCheckChunk(*ch); } } @@ -1833,10 +1839,10 @@ static void SlFixPointers() { _sl.action = SLA_PTRS; - FOR_ALL_CHUNK_HANDLERS(ch) { - if (ch->ptrs_proc != nullptr) { - DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch->id >> 24, ch->id >> 16, ch->id >> 8, ch->id); - ch->ptrs_proc(); + for (auto &ch : ChunkHandlers()) { + if (ch.ptrs_proc != nullptr) { + DEBUG(sl, 3, "Fixing pointers for %c%c%c%c", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); + ch.ptrs_proc(); } }