CPlayerState: Make g_typeNameMap a compile-time array

While useful as a map, this causes an allocation that occurs during
program start and lasts until the program terminates, even if the
relevant code is never executed.

Given the total number of elements is quite small, we can convert this
into a compile-time array and perform the lookup with that instead.
While we're at it, we can eliminate an unnecessary second lookup into
said array by reusing the iterator from the first find.
This commit is contained in:
Lioncash 2020-03-21 00:57:03 -04:00
parent 36ac0a8d78
commit 83c9af9153
2 changed files with 58 additions and 56 deletions

View File

@ -389,62 +389,66 @@ void CPlayerState::InitializeScanTimes() {
u32 CPlayerState::GetPowerUpMaxValue(EItemType type) { return PowerUpMaxValues[size_t(type)]; } u32 CPlayerState::GetPowerUpMaxValue(EItemType type) { return PowerUpMaxValues[size_t(type)]; }
const std::unordered_map<std::string_view, CPlayerState::EItemType> CPlayerState::g_TypeNameMap = {
{"powerbeam"sv, EItemType::PowerBeam},
{"icebeam"sv, EItemType::IceBeam},
{"wavebeam"sv, EItemType::WaveBeam},
{"plasmabeam"sv, EItemType::PlasmaBeam},
{"missiles"sv, EItemType::Missiles},
{"scanvisor"sv, EItemType::ScanVisor},
{"bombs"sv, EItemType::MorphBallBombs},
{"ballbombs"sv, EItemType::MorphBallBombs},
{"morphballbombs"sv, EItemType::MorphBallBombs},
{"powerbombs"sv, EItemType::PowerBombs},
{"flamethrower"sv, EItemType::Flamethrower},
{"thermalvisor"sv, EItemType::ThermalVisor},
{"chargebeam"sv, EItemType::ChargeBeam},
{"supermissile"sv, EItemType::SuperMissile},
{"grapple"sv, EItemType::GrappleBeam},
{"grapplebeam"sv, EItemType::GrappleBeam},
{"xrayvisor"sv, EItemType::XRayVisor},
{"icespreader"sv, EItemType::IceSpreader},
{"spacejump"sv, EItemType::SpaceJumpBoots},
{"spacejumpboots"sv, EItemType::SpaceJumpBoots},
{"morphball"sv, EItemType::MorphBall},
{"combatvisor"sv, EItemType::CombatVisor},
{"boostball"sv, EItemType::BoostBall},
{"spiderball"sv, EItemType::SpiderBall},
{"powersuit"sv, EItemType::PowerSuit},
{"gravitysuit"sv, EItemType::GravitySuit},
{"variasuit"sv, EItemType::VariaSuit},
{"phazonsuit"sv, EItemType::PhazonSuit},
{"energytanks"sv, EItemType::EnergyTanks},
{"unknownitem1"sv, EItemType::UnknownItem1},
{"healthrefill"sv, EItemType::HealthRefill},
{"health"sv, EItemType::HealthRefill},
{"unknownitem2"sv, EItemType::UnknownItem2},
{"wavebuster"sv, EItemType::Wavebuster},
{"truth"sv, EItemType::Truth},
{"strength"sv, EItemType::Strength},
{"elder"sv, EItemType::Elder},
{"wild"sv, EItemType::Wild},
{"lifegiver"sv, EItemType::Lifegiver},
{"warrior"sv, EItemType::Warrior},
{"chozo"sv, EItemType::Chozo},
{"nature"sv, EItemType::Nature},
{"sun"sv, EItemType::Sun},
{"world"sv, EItemType::World},
{"spirit"sv, EItemType::Spirit},
{"newborn"sv, EItemType::Newborn},
};
CPlayerState::EItemType CPlayerState::ItemNameToType(std::string_view name) { CPlayerState::EItemType CPlayerState::ItemNameToType(std::string_view name) {
std::string lowName = name.data(); static constexpr std::array<std::pair<std::string_view, EItemType>, 46> typeNameMap{{
athena::utility::tolower(lowName); {"powerbeam"sv, EItemType::PowerBeam},
if (g_TypeNameMap.find(lowName) == g_TypeNameMap.end()) {"icebeam"sv, EItemType::IceBeam},
return EItemType::Invalid; {"wavebeam"sv, EItemType::WaveBeam},
{"plasmabeam"sv, EItemType::PlasmaBeam},
{"missiles"sv, EItemType::Missiles},
{"scanvisor"sv, EItemType::ScanVisor},
{"bombs"sv, EItemType::MorphBallBombs},
{"ballbombs"sv, EItemType::MorphBallBombs},
{"morphballbombs"sv, EItemType::MorphBallBombs},
{"powerbombs"sv, EItemType::PowerBombs},
{"flamethrower"sv, EItemType::Flamethrower},
{"thermalvisor"sv, EItemType::ThermalVisor},
{"chargebeam"sv, EItemType::ChargeBeam},
{"supermissile"sv, EItemType::SuperMissile},
{"grapple"sv, EItemType::GrappleBeam},
{"grapplebeam"sv, EItemType::GrappleBeam},
{"xrayvisor"sv, EItemType::XRayVisor},
{"icespreader"sv, EItemType::IceSpreader},
{"spacejump"sv, EItemType::SpaceJumpBoots},
{"spacejumpboots"sv, EItemType::SpaceJumpBoots},
{"morphball"sv, EItemType::MorphBall},
{"combatvisor"sv, EItemType::CombatVisor},
{"boostball"sv, EItemType::BoostBall},
{"spiderball"sv, EItemType::SpiderBall},
{"powersuit"sv, EItemType::PowerSuit},
{"gravitysuit"sv, EItemType::GravitySuit},
{"variasuit"sv, EItemType::VariaSuit},
{"phazonsuit"sv, EItemType::PhazonSuit},
{"energytanks"sv, EItemType::EnergyTanks},
{"unknownitem1"sv, EItemType::UnknownItem1},
{"healthrefill"sv, EItemType::HealthRefill},
{"health"sv, EItemType::HealthRefill},
{"unknownitem2"sv, EItemType::UnknownItem2},
{"wavebuster"sv, EItemType::Wavebuster},
{"truth"sv, EItemType::Truth},
{"strength"sv, EItemType::Strength},
{"elder"sv, EItemType::Elder},
{"wild"sv, EItemType::Wild},
{"lifegiver"sv, EItemType::Lifegiver},
{"warrior"sv, EItemType::Warrior},
{"chozo"sv, EItemType::Chozo},
{"nature"sv, EItemType::Nature},
{"sun"sv, EItemType::Sun},
{"world"sv, EItemType::World},
{"spirit"sv, EItemType::Spirit},
{"newborn"sv, EItemType::Newborn},
}};
return g_TypeNameMap.find(lowName)->second; std::string lowName{name};
athena::utility::tolower(lowName);
const auto iter = std::find_if(typeNameMap.cbegin(), typeNameMap.cend(),
[&lowName](const auto& entry) { return entry.first == lowName; });
if (iter == typeNameMap.cend()) {
return EItemType::Invalid;
}
return iter->second;
} }
} // namespace urde } // namespace urde

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <string_view> #include <string_view>
#include <unordered_map>
#include <vector> #include <vector>
#include "Runtime/CStaticInterference.hpp" #include "Runtime/CStaticInterference.hpp"
@ -89,7 +88,6 @@ public:
enum class EBeamId : s32 { Invalid = -1, Power, Ice, Wave, Plasma, Phazon, Phazon2 = 27 }; enum class EBeamId : s32 { Invalid = -1, Power, Ice, Wave, Plasma, Phazon, Phazon2 = 27 };
private: private:
static const std::unordered_map<std::string_view, EItemType> g_TypeNameMap;
struct CPowerUp { struct CPowerUp {
u32 x0_amount = 0; u32 x0_amount = 0;
u32 x4_capacity = 0; u32 x4_capacity = 0;