1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00

Deduplicate the code, add more safety checks

This commit is contained in:
ζeh Matt
2024-12-04 17:14:02 +02:00
parent 116cb2d712
commit dd78366a4c
2 changed files with 50 additions and 83 deletions

View File

@@ -16,6 +16,35 @@
using namespace OpenRCT2;
template<typename T>
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<T>(value));
}
template<typename T>
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<T>(data));
return std::get<T>(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<int64_t>(value));
putExtraImpl(_Data, key, static_cast<int64_t>(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<int64_t>(value));
putExtraImpl(_Data, key, static_cast<int64_t>(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<void*>(data));
return std::get<void*>(data);
return getExtraImpl<void*>(_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<int64_t>(data));
return static_cast<uint32_t>(std::get<int64_t>(data));
return static_cast<uint32_t>(getExtraImpl<int64_t>(_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<int64_t>(data));
return static_cast<int32_t>(std::get<int64_t>(data));
return static_cast<uint32_t>(getExtraImpl<int64_t>(_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<std::string>(data));
return std::get<std::string>(data);
return getExtraImpl<std::string>(_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<close_callback>(data));
return std::get<close_callback>(data);
return getExtraImpl<close_callback>(_Data, key);
}

View File

@@ -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<int64_t, std::string, close_callback, void*>;
using IntentDataEntry = std::pair<uint32_t, IntentData>;
using IntentDataStorage = sfl::static_vector<IntentDataEntry, kIntentMaxDataSlots>;
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<int64_t, std::string, close_callback, void*>;
WindowClass _Class{ WindowClass::Null };
WindowDetail _WindowDetail{ WD_NULL };
IntentAction _Action{ INTENT_ACTION_NULL };
using DataEntry = std::pair<uint32_t, IntentData>;
sfl::static_vector<DataEntry, kMaxDataSlots> _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);