From dd78366a4c236ab63a9dcf5aeedb8446c06ba966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:14:02 +0200 Subject: [PATCH] Deduplicate the code, add more safety checks --- src/openrct2/windows/Intent.cpp | 114 +++++++++++--------------------- src/openrct2/windows/Intent.h | 19 +++--- 2 files changed, 50 insertions(+), 83 deletions(-) diff --git a/src/openrct2/windows/Intent.cpp b/src/openrct2/windows/Intent.cpp index 61fe133c27..0430cac15e 100644 --- a/src/openrct2/windows/Intent.cpp +++ b/src/openrct2/windows/Intent.cpp @@ -16,6 +16,35 @@ using namespace OpenRCT2; +template +static void putExtraImpl(IntentDataStorage& storage, uint32_t key, T&& value) +{ + auto it = std::ranges::lower_bound(storage, key, {}, &IntentDataEntry::first); + + // Key should not already exist. + assert(it == storage.end() || it->first != key); + + storage.emplace(it, key, std::forward(value)); +} + +template +static auto getExtraImpl(const IntentDataStorage& storage, uint32_t key) +{ + auto it = std::ranges::lower_bound(storage, key, {}, &IntentDataEntry::first); + if (it == storage.end() || it->first != key) + { + // If key does not exist then the usage of Intent is incorrect. + assert(false); + + return T{}; + } + + const auto& [_, data] = *it; + assert(std::holds_alternative(data)); + + return std::get(data); +} + Intent::Intent(WindowClass windowClass) : _Class(windowClass) { @@ -33,51 +62,31 @@ Intent::Intent(IntentAction intentAction) Intent* Intent::PutExtra(uint32_t key, uint32_t value) { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - assert(it == _Data.end() || it->first != key); - - _Data.emplace(it, key, static_cast(value)); - + putExtraImpl(_Data, key, static_cast(value)); return this; } Intent* Intent::PutExtra(uint32_t key, void* value) { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - assert(it == _Data.end() || it->first != key); - - _Data.emplace(it, key, value); - + putExtraImpl(_Data, key, value); return this; } Intent* Intent::PutExtra(uint32_t key, int32_t value) { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - assert(it == _Data.end() || it->first != key); - - _Data.emplace(it, key, static_cast(value)); - + putExtraImpl(_Data, key, static_cast(value)); return this; } Intent* Intent::PutExtra(uint32_t key, std::string value) { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - assert(it == _Data.end() || it->first != key); - - _Data.emplace(it, key, std::move(value)); - + putExtraImpl(_Data, key, std::move(value)); return this; } Intent* Intent::PutExtra(uint32_t key, close_callback value) { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - assert(it == _Data.end() || it->first != key); - - _Data.emplace(it, key, value); - + putExtraImpl(_Data, key, value); return this; } @@ -98,70 +107,25 @@ IntentAction Intent::GetAction() const void* Intent::GetPointerExtra(uint32_t key) const { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - if (it == _Data.end() || it->first != key) - { - return nullptr; - } - - const auto& [_, data] = *it; - - assert(std::holds_alternative(data)); - return std::get(data); + return getExtraImpl(_Data, key); } uint32_t Intent::GetUIntExtra(uint32_t key) const { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - if (it == _Data.end() || it->first != key) - { - return 0; - } - - const auto& [_, data] = *it; - - assert(std::holds_alternative(data)); - return static_cast(std::get(data)); + return static_cast(getExtraImpl(_Data, key)); } int32_t Intent::GetSIntExtra(uint32_t key) const { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - if (it == _Data.end() || it->first != key) - { - return 0; - } - - const auto& [_, data] = *it; - - assert(std::holds_alternative(data)); - return static_cast(std::get(data)); + return static_cast(getExtraImpl(_Data, key)); } std::string Intent::GetStringExtra(uint32_t key) const { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - if (it == _Data.end() || it->first != key) - { - return std::string{}; - } - - const auto& [_, data] = *it; - - assert(std::holds_alternative(data)); - return std::get(data); + return getExtraImpl(_Data, key); } close_callback Intent::GetCloseCallbackExtra(uint32_t key) const { - auto it = std::ranges::lower_bound(_Data, key, {}, &DataEntry::first); - if (it == _Data.end() || it->first != key) - { - return nullptr; - } - - const auto& [_, data] = *it; - - assert(std::holds_alternative(data)); - return std::get(data); + return getExtraImpl(_Data, key); } diff --git a/src/openrct2/windows/Intent.h b/src/openrct2/windows/Intent.h index 7b71b1954d..6983010a97 100644 --- a/src/openrct2/windows/Intent.h +++ b/src/openrct2/windows/Intent.h @@ -59,32 +59,35 @@ enum IntentAction INTENT_ACTION_NULL = 255, }; +// The maximum amount of data the Intent can hold, 8 should be sufficient, raise this if needed. +static constexpr size_t kIntentMaxDataSlots = 8; + +using IntentData = std::variant; +using IntentDataEntry = std::pair; +using IntentDataStorage = sfl::static_vector; + class Intent { - // The maximum amount of data the Intent can hold, 8 should be sufficient, raise this if needed. - static constexpr size_t kMaxDataSlots = 8; - - using IntentData = std::variant; - WindowClass _Class{ WindowClass::Null }; WindowDetail _WindowDetail{ WD_NULL }; IntentAction _Action{ INTENT_ACTION_NULL }; - - using DataEntry = std::pair; - sfl::static_vector _Data; + IntentDataStorage _Data; public: explicit Intent(WindowClass windowClass); explicit Intent(WindowDetail windowDetail); explicit Intent(IntentAction windowclass); + WindowClass GetWindowClass() const; WindowDetail GetWindowDetail() const; IntentAction GetAction() const; + void* GetPointerExtra(uint32_t key) const; std::string GetStringExtra(uint32_t key) const; uint32_t GetUIntExtra(uint32_t key) const; int32_t GetSIntExtra(uint32_t key) const; close_callback GetCloseCallbackExtra(uint32_t key) const; + Intent* PutExtra(uint32_t key, uint32_t value); Intent* PutExtra(uint32_t key, void* value); Intent* PutExtra(uint32_t key, int32_t value);