From 774c72e1d15dbfb018df86925bf9b8bbd4f56fd4 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 13 Sep 2016 18:14:47 +0100 Subject: [PATCH] Remove usage of List and refactor S4Importer Extending the collection classes isn't being adopted enough and adds to much maintenance. Use collection utility methods instead. --- openrct2.vcxproj | 1 + src/core/Collections.hpp | 103 +++++++++++++++++++++++++++++ src/rct1/S4Importer.cpp | 138 ++++++++++++++++++++++----------------- src/rct1/Tables.h | 6 +- src/rct1/tables.cpp | 8 +-- 5 files changed, 188 insertions(+), 68 deletions(-) create mode 100644 src/core/Collections.hpp diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 716432f64f..a92c9f7118 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -363,6 +363,7 @@ + diff --git a/src/core/Collections.hpp b/src/core/Collections.hpp new file mode 100644 index 0000000000..a5264d2d0f --- /dev/null +++ b/src/core/Collections.hpp @@ -0,0 +1,103 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include +#include "../common.h" + +namespace Collections +{ + template + void AddRange(TCollection &collection, std::initializer_list initializerList) + { + collection.insert(collection.end(), initializerList.begin(), initializerList.end()); + } + + template + bool Contains(TCollection &collection, TItem needle, TComparer comparer) + { + for (TItem item : collection) + { + if (comparer(item, needle)) + { + return true; + } + } + return false; + } + + template + size_t IndexOf(TCollection &collection, TItem needle, TComparer comparer) + { + size_t index = 0; + for (TItem item : collection) + { + if (comparer(item, needle)) + { + return index; + } + index++; + } + return SIZE_MAX; + } + + #pragma region String helpers + + template + bool Contains(TCollection &collection, const char * item, bool ignoreCase = false) + { + if (ignoreCase) + { + return Contains(collection, item, + [](const auto &a, const auto &b) + { + return String::Equals(a, b, true); + }); + } + else + { + return Contains(collection, item, + [](const auto &a, const auto &b) + { + return String::Equals(a, b, false); + }); + } + } + + template + size_t IndexOf(TCollection &collection, const char * item, bool ignoreCase = false) + { + if (ignoreCase) + { + return IndexOf(collection, item, + [](const auto &a, const auto &b) + { + return String::Equals(a, b, true); + }); + } + else + { + return IndexOf(collection, item, + [](const auto &a, const auto &b) + { + return String::Equals(a, b, false); + }); + } + } + + #pragma endregion +} diff --git a/src/rct1/S4Importer.cpp b/src/rct1/S4Importer.cpp index cf8e3a510c..64ff11db58 100644 --- a/src/rct1/S4Importer.cpp +++ b/src/rct1/S4Importer.cpp @@ -14,10 +14,12 @@ *****************************************************************************/ #pragma endregion +#include +#include "../core/Collections.hpp" #include "../core/Console.hpp" #include "../core/Exception.hpp" #include "../core/Guard.hpp" -#include "../core/List.hpp" +#include "../core/Memory.hpp" #include "../core/Path.hpp" #include "../core/String.hpp" #include "../core/Util.hpp" @@ -51,10 +53,38 @@ extern "C" #include "../ride/ride_data.h" } -static bool ObjectNameComparer(const char * a, const char * b) +class EntryList { - return String::Equals(a, b, true); -} +private: + std::vector _entries; + +public: + size_t GetCount() const + { + return _entries.size(); + } + + const std::vector & GetEntries() const + { + return _entries; + } + + size_t GetOrAddEntry(const char * entryName) + { + size_t entryIndex = Collections::IndexOf(_entries, entryName, true); + if (entryIndex == SIZE_MAX) + { + entryIndex = _entries.size(); + _entries.push_back(entryName); + } + return entryIndex; + } + + void AddRange(std::initializer_list initializerList) + { + Collections::AddRange(_entries, initializerList); + } +}; class S4Importer : public IS4Importer { @@ -64,13 +94,13 @@ private: uint8 _gameVersion; // Lists of dynamic object entries - List _rideEntries; - List _smallSceneryEntries; - List _largeSceneryEntries; - List _wallEntries; - List _pathEntries; - List _pathAdditionEntries; - List _sceneryGroupEntries; + EntryList _rideEntries; + EntryList _smallSceneryEntries; + EntryList _largeSceneryEntries; + EntryList _wallEntries; + EntryList _pathEntries; + EntryList _pathAdditionEntries; + EntryList _sceneryGroupEntries; // Lookup tables for converting from RCT1 hard coded types to the new dynamic object entries uint8 _rideTypeToRideEntryMap[96]; @@ -335,7 +365,7 @@ private: if (sceneryTheme != 0 && _sceneryThemeTypeToEntryMap[sceneryTheme] == 255) continue; - List objects = RCT1::GetSceneryObjects(sceneryTheme); + std::vector objects = RCT1::GetSceneryObjects(sceneryTheme); for (const char * objectName : objects) { rct_object_entry * foundEntry = object_list_find_by_name(objectName); @@ -349,17 +379,13 @@ private: case OBJECT_TYPE_PATHS: case OBJECT_TYPE_PATH_BITS: { - List * entries = GetEntryList(objectType); + EntryList * entries = GetEntryList(objectType); - // Ran out of available entries - if (entries->GetCount() >= (size_t)object_entry_group_counts[objectType]) + // Check if there are spare entries available + size_t maxEntries = (size_t)object_entry_group_counts[objectType]; + if (entries->GetCount() < maxEntries) { - break; - } - - if (!entries->Contains(objectName, ObjectNameComparer)) - { - entries->Add(objectName); + entries->GetOrAddEntry(objectName); } break; } @@ -375,13 +401,8 @@ private: if (_rideTypeToRideEntryMap[rideType] == 255) { const char * entryName = RCT1::GetRideTypeObject(rideType); + size_t entryIndex = _rideEntries.GetOrAddEntry(entryName); - size_t entryIndex = _rideEntries.IndexOf(entryName, ObjectNameComparer); - if (entryIndex == SIZE_MAX) - { - entryIndex = _rideEntries.GetCount(); - _rideEntries.Add(entryName); - } _rideTypeToRideEntryMap[rideType] = (uint8)entryIndex; } } @@ -392,13 +413,8 @@ private: if (_vehicleTypeToRideEntryMap[vehicleType] == 255) { const char * entryName = RCT1::GetVehicleObject(vehicleType); + size_t entryIndex = _rideEntries.GetOrAddEntry(entryName); - size_t entryIndex = _rideEntries.IndexOf(entryName, ObjectNameComparer); - if (entryIndex == SIZE_MAX) - { - entryIndex = _rideEntries.GetCount(); - _rideEntries.Add(entryName); - } _vehicleTypeToRideEntryMap[vehicleType] = (uint8)entryIndex; _rideTypeToRideEntryMap[rideType] = (uint8)entryIndex; } @@ -410,8 +426,9 @@ private: if (_smallSceneryTypeToEntryMap[smallSceneryType] == 255) { const char * entryName = RCT1::GetSmallSceneryObject(smallSceneryType); - _smallSceneryTypeToEntryMap[smallSceneryType] = (uint8)_smallSceneryEntries.GetCount(); - _smallSceneryEntries.Add(entryName); + size_t entryIndex = _smallSceneryEntries.GetOrAddEntry(entryName); + + _smallSceneryTypeToEntryMap[smallSceneryType] = (uint8)entryIndex; } } @@ -421,8 +438,9 @@ private: if (_largeSceneryTypeToEntryMap[largeSceneryType] == 255) { const char * entryName = RCT1::GetLargeSceneryObject(largeSceneryType); - _largeSceneryTypeToEntryMap[largeSceneryType] = (uint8)_largeSceneryEntries.GetCount(); - _largeSceneryEntries.Add(entryName); + size_t entryIndex = _largeSceneryEntries.GetOrAddEntry(entryName); + + _largeSceneryTypeToEntryMap[largeSceneryType] = (uint8)entryIndex; } } @@ -432,8 +450,9 @@ private: if (_wallTypeToEntryMap[wallType] == 255) { const char * entryName = RCT1::GetWallObject(wallType); - _wallTypeToEntryMap[wallType] = (uint8)_wallEntries.GetCount(); - _wallEntries.Add(entryName); + size_t entryIndex = _wallEntries.GetOrAddEntry(entryName); + + _wallTypeToEntryMap[wallType] = (uint8)entryIndex; } } @@ -443,17 +462,9 @@ private: if (_pathTypeToEntryMap[pathType] == 255) { const char * entryName = RCT1::GetPathObject(pathType); + size_t entryIndex = _pathEntries.GetOrAddEntry(entryName); - size_t index = _pathEntries.IndexOf(entryName, ObjectNameComparer); - if (index != SIZE_MAX) - { - _pathTypeToEntryMap[pathType] = (uint8)index; - } - else - { - _pathTypeToEntryMap[pathType] = (uint8)_pathEntries.GetCount(); - _pathEntries.Add(entryName); - } + _pathTypeToEntryMap[pathType] = (uint8)entryIndex; } } @@ -467,8 +478,9 @@ private: if (_pathAdditionTypeToEntryMap[normalisedPathAdditionType] == 255) { const char * entryName = RCT1::GetPathAddtionObject(normalisedPathAdditionType); - _pathAdditionTypeToEntryMap[normalisedPathAdditionType] = (uint8)_pathAdditionEntries.GetCount(); - _pathAdditionEntries.Add(entryName); + size_t entryIndex = _pathAdditionEntries.GetOrAddEntry(entryName); + + _pathAdditionTypeToEntryMap[normalisedPathAdditionType] = (uint8)entryIndex; } _pathAdditionTypeToEntryMap[pathAdditionType] = _pathAdditionTypeToEntryMap[normalisedPathAdditionType]; @@ -486,16 +498,15 @@ private: else { const char * entryName = RCT1::GetSceneryGroupObject(sceneryThemeType); - uint8 entryIndex = (uint8)_sceneryGroupEntries.GetCount(); - if (entryIndex >= 19) + if (_sceneryGroupEntries.GetCount() >= 19) { Console::WriteLine("Warning: More than 19 (max scenery groups) in RCT1 park."); Console::WriteLine(" [%s] scenery group not added.", entryName); } else { - _sceneryThemeTypeToEntryMap[sceneryThemeType] = (uint8)_sceneryGroupEntries.GetCount(); - _sceneryGroupEntries.Add(entryName); + size_t entryIndex = _sceneryGroupEntries.GetOrAddEntry(entryName); + _sceneryThemeTypeToEntryMap[sceneryThemeType] = (uint8)entryIndex; } } } @@ -779,7 +790,7 @@ private: LoadObjects(OBJECT_TYPE_PATHS, _pathEntries); LoadObjects(OBJECT_TYPE_PATH_BITS, _pathAdditionEntries); LoadObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries); - LoadObjects(OBJECT_TYPE_BANNERS, List({ + LoadObjects(OBJECT_TYPE_BANNERS, std::vector({ "BN1 ", "BN2 ", "BN3 ", @@ -790,11 +801,16 @@ private: "BN8 ", "BN9 " })); - LoadObjects(OBJECT_TYPE_PARK_ENTRANCE, List({ "PKENT1 " })); - LoadObjects(OBJECT_TYPE_WATER, List({ "WTRCYAN " })); + LoadObjects(OBJECT_TYPE_PARK_ENTRANCE, std::vector({ "PKENT1 " })); + LoadObjects(OBJECT_TYPE_WATER, std::vector({ "WTRCYAN " })); } - void LoadObjects(uint8 objectType, List entries) + void LoadObjects(uint8 objectType, const EntryList &entries) + { + LoadObjects(objectType, entries.GetEntries()); + } + + void LoadObjects(uint8 objectType, const std::vector &entries) { IObjectManager * objectManager = GetObjectManager(); @@ -1516,7 +1532,7 @@ private: } } - List * GetEntryList(uint8 objectType) + EntryList * GetEntryList(uint8 objectType) { switch (objectType) { case OBJECT_TYPE_RIDE: return &_rideEntries; @@ -1640,7 +1656,7 @@ extern "C" */ int vehicle_preference_compare(uint8 rideType, const char * a, const char * b) { - List rideEntryOrder = RCT1::GetPreferedRideEntryOrder(rideType); + std::vector rideEntryOrder = RCT1::GetPreferedRideEntryOrder(rideType); for (const char * object : rideEntryOrder) { if (String::Equals(object, a, true)) diff --git a/src/rct1/Tables.h b/src/rct1/Tables.h index a06a3854e0..e723ceaffe 100644 --- a/src/rct1/Tables.h +++ b/src/rct1/Tables.h @@ -20,7 +20,7 @@ #ifdef __cplusplus -#include "../core/List.hpp" +#include namespace RCT1 { @@ -42,9 +42,9 @@ namespace RCT1 const char * GetPathAddtionObject(uint8 pathAdditionType); const char * GetSceneryGroupObject(uint8 sceneryGroupType); - const List GetSceneryObjects(uint8 sceneryType); + const std::vector GetSceneryObjects(uint8 sceneryType); - const List GetPreferedRideEntryOrder(uint8 rideType); + const std::vector GetPreferedRideEntryOrder(uint8 rideType); } extern "C" { diff --git a/src/rct1/tables.cpp b/src/rct1/tables.cpp index 7c6f734098..6d1bcac8d7 100644 --- a/src/rct1/tables.cpp +++ b/src/rct1/tables.cpp @@ -962,9 +962,9 @@ namespace RCT1 return map[waterType]; } - const List GetPreferedRideEntryOrder(uint8 rideType) + const std::vector GetPreferedRideEntryOrder(uint8 rideType) { - static const List preferedRideEntryOrder[] = + static const std::vector preferedRideEntryOrder[] = { { "SPDRCR "}, // RIDE_TYPE_SPIRAL_ROLLER_COASTER { "TOGST "}, // RIDE_TYPE_STAND_UP_ROLLER_COASTER @@ -1061,9 +1061,9 @@ namespace RCT1 return preferedRideEntryOrder[rideType]; } - const List GetSceneryObjects(uint8 sceneryType) + const std::vector GetSceneryObjects(uint8 sceneryType) { - static const List map[] = + static const std::vector map[] = { // RCT1_SCENERY_THEME_GENERAL (trees, shrubs, garden, walls, fence, path accessories) { "TIC ", "TLC ", "TMC ", "TMP ", "TITC ", "TGHC ", "TAC ", "TGHC2 ", "TCJ ", "TMBJ ", "TCF ", "TCL ", "TRF ", "TRF2 ", "TEL ", "TAP ", "TSP ", "TMZP ", "TCRP ", "TBP ", "TLP ", "TWP ", "TAS ", "TMG ", "TWW ", "TSB ", "TVL ", "TCY ", "TNS ", "TWN ", "TCE ", "TCO ", "THL ", "TCC ", "TF1 ", "TF2 ", "TCT ", "TH1 ", "TH2 ", "TPM ", "TROPT1 ",