mirror of https://github.com/OpenRCT2/OpenRCT2.git
Add EnumMap container for bidirectional key, enum mapping
This commit is contained in:
parent
1ea9bbbb1b
commit
a36e0a32f7
|
@ -767,6 +767,7 @@
|
|||
F42186C5840D4196981ADD16 /* EntityTweener.h in Headers */ = {isa = PBXBuildFile; fileRef = 091352A950004312BAB18717 /* EntityTweener.h */; };
|
||||
0746674FA0794ABF86E406A1 /* Litter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9D3DD6CD73F5421880280D9D /* Litter.cpp */; };
|
||||
B9B6F97CE24E4A559C7BBA0A /* RideConstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCCA2EF0F5A40D5B83A83AC /* RideConstruction.cpp */; };
|
||||
317B766A750D4365B22A1682 /* EnumMap.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BA2317BF6FB54E328DEB7055 /* EnumMap.hpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -1836,6 +1837,7 @@
|
|||
091352A950004312BAB18717 /* EntityTweener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EntityTweener.h; path = src/openrct2/world/EntityTweener.h; sourceTree = SOURCE_ROOT; };
|
||||
9D3DD6CD73F5421880280D9D /* Litter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Litter.cpp; path = src/openrct2/world/Litter.cpp; sourceTree = SOURCE_ROOT; };
|
||||
6BCCA2EF0F5A40D5B83A83AC /* RideConstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RideConstruction.cpp; path = src/openrct2/ride/RideConstruction.cpp; sourceTree = SOURCE_ROOT; };
|
||||
BA2317BF6FB54E328DEB7055 /* EnumMap.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = EnumMap.hpp; path = src/openrct2/core/EnumMap.hpp; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -2503,6 +2505,7 @@
|
|||
4C8BB67F25533D64005C8830 /* StringReader.h */,
|
||||
F76C83991EC4E7CC00FA49E2 /* Zip.cpp */,
|
||||
F76C839A1EC4E7CC00FA49E2 /* Zip.h */,
|
||||
BA2317BF6FB54E328DEB7055 /* EnumMap.hpp */,
|
||||
);
|
||||
path = core;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3468,6 +3471,7 @@
|
|||
2ADE2F342244191E002598AF /* VirtualFloor.h in Headers */,
|
||||
66A10F8B257F1E1800DD651A /* LandSmoothAction.h in Headers */,
|
||||
F42186C5840D4196981ADD16 /* EntityTweener.h in Headers */,
|
||||
317B766A750D4365B22A1682 /* EnumMap.hpp in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2021 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Bi-directional map for converting between strings and enums / numbers.
|
||||
*/
|
||||
template<typename T> class EnumMap
|
||||
{
|
||||
private:
|
||||
std::vector<std::pair<std::string_view, T>> _map;
|
||||
bool _continiousValueIndex{ false };
|
||||
|
||||
static constexpr size_t BucketSize = 43;
|
||||
std::array<std::vector<int32_t>, BucketSize> _buckets;
|
||||
|
||||
static constexpr bool ValueIndexable()
|
||||
{
|
||||
if constexpr (std::is_enum_v<T>)
|
||||
return true;
|
||||
else if constexpr (std::is_integral_v<T>)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr auto ValueDistance(T a, T b)
|
||||
{
|
||||
if constexpr (std::is_enum_v<T>)
|
||||
return static_cast<std::underlying_type_t<T>>(b) - static_cast<std::underlying_type_t<T>>(a);
|
||||
else if constexpr (std::is_integral_v<T>)
|
||||
return (b - a);
|
||||
}
|
||||
|
||||
static constexpr uint32_t MakeHash(const std::string_view str)
|
||||
{
|
||||
uint32_t res = 0x811c9dc5;
|
||||
for (auto chr : str)
|
||||
{
|
||||
res ^= chr;
|
||||
res *= 0x01000193;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public:
|
||||
EnumMap(const std::initializer_list<std::pair<std::string_view, T>>&& items)
|
||||
: _map{ items }
|
||||
{
|
||||
std::sort(_map.begin(), _map.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
|
||||
|
||||
if constexpr (ValueIndexable())
|
||||
{
|
||||
_continiousValueIndex = true;
|
||||
T cur{};
|
||||
for (size_t i = 1; i < _map.size(); i++)
|
||||
{
|
||||
auto nextVal = _map[i].second;
|
||||
auto dist = ValueDistance(cur, _map[i].second);
|
||||
if (dist != 1)
|
||||
{
|
||||
_continiousValueIndex = false;
|
||||
break;
|
||||
}
|
||||
cur = nextVal;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t index = 0;
|
||||
for (auto& kv : _map)
|
||||
{
|
||||
auto hash = MakeHash(kv.first);
|
||||
auto bucketIndex = hash % BucketSize;
|
||||
auto& bucket = _buckets[bucketIndex];
|
||||
bucket.push_back(index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view operator[](T k) const
|
||||
{
|
||||
auto it = find(k);
|
||||
return it->first;
|
||||
}
|
||||
|
||||
T operator[](std::string_view k) const
|
||||
{
|
||||
auto it = find(k);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto find(const std::string_view k) const
|
||||
{
|
||||
const auto hash = MakeHash(k);
|
||||
const auto bucketIndex = hash % BucketSize;
|
||||
const auto& bucket = _buckets[bucketIndex];
|
||||
|
||||
for (auto index : bucket)
|
||||
{
|
||||
auto& entry = _map[index];
|
||||
if (entry.first == k)
|
||||
{
|
||||
return _map.begin() + index;
|
||||
}
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
auto find(const T k) const
|
||||
{
|
||||
const auto binarySearchValue = [&]() {
|
||||
auto it = std::lower_bound(_map.begin(), _map.end(), k, [](const auto& a, const auto& b) { return a.second < b; });
|
||||
if (it == _map.end() || it->second != k)
|
||||
return end();
|
||||
|
||||
return it;
|
||||
};
|
||||
|
||||
if constexpr (ValueIndexable())
|
||||
{
|
||||
if (_continiousValueIndex)
|
||||
{
|
||||
auto index = static_cast<size_t>(k);
|
||||
return _map.begin() + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
return binarySearchValue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return binarySearchValue();
|
||||
}
|
||||
}
|
||||
|
||||
auto begin() const
|
||||
{
|
||||
return _map.begin();
|
||||
}
|
||||
|
||||
auto end() const
|
||||
{
|
||||
return _map.end();
|
||||
}
|
||||
};
|
|
@ -157,6 +157,7 @@
|
|||
<ClInclude Include="core\DataSerialiserTraits.h" />
|
||||
<ClInclude Include="core\Diagnostics.hpp" />
|
||||
<ClInclude Include="core\Endianness.h" />
|
||||
<ClInclude Include="core\EnumMap.hpp" />
|
||||
<ClInclude Include="core\File.h" />
|
||||
<ClInclude Include="core\FileIndex.hpp" />
|
||||
<ClInclude Include="core\FileScanner.h" />
|
||||
|
|
Loading…
Reference in New Issue