Config: Flatten structures

Originally, Layer contained a std::map of Sections, which containted a std::map
containing the (key, value) pairs. Here we flattern this structure so that only
one std::map is required, reducing the number of indirections required and
vastly simplifying the code.
This commit is contained in:
MerryMage
2017-10-29 19:11:15 +00:00
parent f3b52c07d7
commit 4c24629b95
13 changed files with 220 additions and 551 deletions

View File

@ -199,10 +199,10 @@ public:
{
}
void Load(Config::Layer* config_layer) override
void Load(Config::Layer* layer) override
{
IniFile ini;
if (config_layer->GetLayer() == Config::LayerType::GlobalGame)
if (layer->GetLayer() == Config::LayerType::GlobalGame)
{
for (const std::string& filename : GetGameIniFilenames(m_id, m_revision))
ini.Load(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename, true);
@ -217,16 +217,16 @@ public:
for (const auto& section : system_sections)
{
LoadFromSystemSection(config_layer, section);
LoadFromSystemSection(layer, section);
}
LoadControllerConfig(config_layer);
LoadControllerConfig(layer);
}
void Save(Config::Layer* config_layer) override;
void Save(Config::Layer* layer) override;
private:
void LoadControllerConfig(Config::Layer* config_layer) const
void LoadControllerConfig(Config::Layer* layer) const
{
// Game INIs can have controller profiles embedded in to them
static const std::array<char, 4> nums = {{'1', '2', '3', '4'}};
@ -244,82 +244,53 @@ private:
std::string type = std::get<0>(use_data);
std::string path = "Profiles/" + std::get<1>(use_data) + "/";
Config::Section* control_section =
config_layer->GetOrCreateSection(std::get<2>(use_data), "Controls");
const auto control_section = [&](std::string key) {
return Config::ConfigLocation{std::get<2>(use_data), "Controls", key};
};
for (const char num : nums)
{
bool use_profile = false;
std::string profile;
if (control_section->Exists(type + "Profile" + num))
if (auto profile = layer->Get<std::string>(control_section(type + "Profile" + num)))
{
if (control_section->Get(type + "Profile" + num, &profile))
std::string ini_path = File::GetUserPath(D_CONFIG_IDX) + path + *profile + ".ini";
if (!File::Exists(ini_path))
{
if (File::Exists(File::GetUserPath(D_CONFIG_IDX) + path + profile + ".ini"))
{
use_profile = true;
}
else
{
// TODO: PanicAlert shouldn't be used for this.
PanicAlertT("Selected controller profile does not exist");
}
// TODO: PanicAlert shouldn't be used for this.
PanicAlertT("Selected controller profile does not exist");
continue;
}
}
if (use_profile)
{
IniFile profile_ini;
profile_ini.Load(File::GetUserPath(D_CONFIG_IDX) + path + profile + ".ini");
profile_ini.Load(ini_path);
const IniFile::Section* ini_section = profile_ini.GetOrCreateSection("Profile");
const IniFile::Section::SectionMap& section_map = ini_section->GetValues();
for (const auto& value : section_map)
{
Config::Section* section = config_layer->GetOrCreateSection(
std::get<2>(use_data), std::get<1>(use_data) + num);
section->Set(value.first, value.second);
Config::ConfigLocation location{std::get<2>(use_data), std::get<1>(use_data) + num,
value.first};
layer->Set(location, value.second);
}
}
}
}
}
void LoadFromSystemSection(Config::Layer* config_layer, const IniFile::Section& section) const
void LoadFromSystemSection(Config::Layer* layer, const IniFile::Section& section) const
{
const std::string section_name = section.GetName();
if (section.HasLines())
{
// Trash INI File chunks
std::vector<std::string> chunk;
section.GetLines(&chunk, true);
if (chunk.size())
{
const auto mapped_config = MapINIToRealLocation(section_name, "");
if (mapped_config.section.empty() && mapped_config.key.empty())
return;
auto* config_section =
config_layer->GetOrCreateSection(mapped_config.system, mapped_config.section);
config_section->SetLines(chunk);
}
}
// Regular key,value pairs
const IniFile::Section::SectionMap& section_map = section.GetValues();
for (const auto& value : section_map)
{
const auto mapped_config = MapINIToRealLocation(section_name, value.first);
const auto location = MapINIToRealLocation(section_name, value.first);
if (mapped_config.section.empty() && mapped_config.key.empty())
if (location.section.empty() && location.key.empty())
continue;
auto* config_section =
config_layer->GetOrCreateSection(mapped_config.system, mapped_config.section);
config_section->Set(mapped_config.key, value.second);
layer->Set(location, value.second);
}
}
@ -327,32 +298,35 @@ private:
const u16 m_revision;
};
void INIGameConfigLayerLoader::Save(Config::Layer* config_layer)
void INIGameConfigLayerLoader::Save(Config::Layer* layer)
{
if (config_layer->GetLayer() != Config::LayerType::LocalGame)
if (layer->GetLayer() != Config::LayerType::LocalGame)
return;
IniFile ini;
for (const std::string& file_name : GetGameIniFilenames(m_id, m_revision))
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + file_name, true);
for (const auto& system : config_layer->GetLayerMap())
for (const auto& config : layer->GetLayerMap())
{
for (const auto& section : system.second)
const Config::ConfigLocation& location = config.first;
const std::optional<std::string>& value = config.second;
if (!IsSettingSaveable(location))
continue;
const auto ini_location = GetINILocationFromConfig(location);
if (ini_location.first.empty() && ini_location.second.empty())
continue;
if (value)
{
for (const auto& value : section->GetValues())
{
if (!IsSettingSaveable({system.first, section->GetName(), value.first}))
continue;
const auto ini_location =
GetINILocationFromConfig({system.first, section->GetName(), value.first});
if (ini_location.first.empty() && ini_location.second.empty())
continue;
IniFile::Section* ini_section = ini.GetOrCreateSection(ini_location.first);
ini_section->Set(ini_location.second, value.second);
}
IniFile::Section* ini_section = ini.GetOrCreateSection(ini_location.first);
ini_section->Set(ini_location.second, *value);
}
else
{
ini.DeleteKey(ini_location.first, ini_location.second);
}
}