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

@ -6,7 +6,6 @@ set(SRCS
Config/Config.cpp Config/Config.cpp
Config/ConfigInfo.cpp Config/ConfigInfo.cpp
Config/Layer.cpp Config/Layer.cpp
Config/Section.cpp
Crypto/AES.cpp Crypto/AES.cpp
Crypto/bn.cpp Crypto/bn.cpp
Crypto/ec.cpp Crypto/ec.cpp

View File

@ -133,7 +133,7 @@ LayerType GetActiveLayerForConfig(const ConfigLocation& config)
if (!LayerExists(layer)) if (!LayerExists(layer))
continue; continue;
if (GetLayer(layer)->Exists(config.system, config.section, config.key)) if (GetLayer(layer)->Exists(config))
return layer; return layer;
} }

View File

@ -12,7 +12,6 @@
#include "Common/Config/ConfigInfo.h" #include "Common/Config/ConfigInfo.h"
#include "Common/Config/Enums.h" #include "Common/Config/Enums.h"
#include "Common/Config/Layer.h" #include "Common/Config/Layer.h"
#include "Common/Config/Section.h"
namespace Config namespace Config
{ {

View File

@ -8,10 +8,47 @@
#include "Common/Config/Config.h" #include "Common/Config/Config.h"
#include "Common/Config/Layer.h" #include "Common/Config/Layer.h"
#include "Common/Config/Section.h"
namespace Config namespace Config
{ {
namespace detail
{
std::string ValueToString(u16 value)
{
return StringFromFormat("0x%04x", value);
}
std::string ValueToString(u32 value)
{
return StringFromFormat("0x%08x", value);
}
std::string ValueToString(float value)
{
return StringFromFormat("%#.9g", value);
}
std::string ValueToString(double value)
{
return StringFromFormat("%#.17g", value);
}
std::string ValueToString(int value)
{
return std::to_string(value);
}
std::string ValueToString(bool value)
{
return StringFromBool(value);
}
std::string ValueToString(const std::string& value)
{
return value;
}
}
ConfigLayerLoader::ConfigLayerLoader(LayerType layer) : m_layer(layer) ConfigLayerLoader::ConfigLayerLoader(LayerType layer) : m_layer(layer)
{ {
} }
@ -38,56 +75,44 @@ Layer::~Layer()
Save(); Save();
} }
bool Layer::Exists(System system, const std::string& section_name, const std::string& key) bool Layer::Exists(const ConfigLocation& location) const
{ {
Section* section = GetSection(system, section_name); const auto iter = m_map.find(location);
if (!section) return iter != m_map.end() && iter->second.has_value();
return false;
return section->Exists(key);
} }
bool Layer::DeleteKey(System system, const std::string& section_name, const std::string& key) bool Layer::DeleteKey(const ConfigLocation& location)
{ {
Section* section = GetSection(system, section_name); m_is_dirty = true;
if (!section) bool had_value = m_map[location].has_value();
return false; m_map[location].reset();
return section->Delete(key); return had_value;
} }
Section* Layer::GetSection(System system, const std::string& section_name) void Layer::DeleteAllKeys()
{ {
for (auto& section : m_sections[system]) m_is_dirty = true;
if (!strcasecmp(section->m_name.c_str(), section_name.c_str())) for (auto& pair : m_map)
return section.get();
return nullptr;
}
Section* Layer::GetOrCreateSection(System system, const std::string& section_name)
{
Section* section = GetSection(system, section_name);
if (!section)
{ {
m_sections[system].emplace_back(std::make_unique<Section>(m_layer, system, section_name)); pair.second.reset();
section = m_sections[system].back().get();
} }
return section;
} }
void Layer::Load() void Layer::Load()
{ {
if (m_loader) if (m_loader)
m_loader->Load(this); m_loader->Load(this);
ClearDirty(); m_is_dirty = false;
InvokeConfigChangedCallbacks(); InvokeConfigChangedCallbacks();
} }
void Layer::Save() void Layer::Save()
{ {
if (!m_loader || !IsDirty()) if (!m_loader || !m_is_dirty)
return; return;
m_loader->Save(this); m_loader->Save(this);
ClearDirty(); m_is_dirty = false;
InvokeConfigChangedCallbacks(); InvokeConfigChangedCallbacks();
} }
@ -98,22 +123,6 @@ LayerType Layer::GetLayer() const
const LayerMap& Layer::GetLayerMap() const const LayerMap& Layer::GetLayerMap() const
{ {
return m_sections; return m_map;
}
bool Layer::IsDirty() const
{
return std::any_of(m_sections.begin(), m_sections.end(), [](const auto& system) {
return std::any_of(system.second.begin(), system.second.end(),
[](const auto& section) { return section->IsDirty(); });
});
}
void Layer::ClearDirty()
{
std::for_each(m_sections.begin(), m_sections.end(), [](auto& system) {
std::for_each(system.second.begin(), system.second.end(),
[](auto& section) { section->ClearDirty(); });
});
} }
} }

View File

@ -6,18 +6,47 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Enums.h" #include "Common/Config/Enums.h"
#include "Common/Config/Section.h" #include "Common/StringUtil.h"
namespace Config namespace Config
{ {
namespace detail
{
std::string ValueToString(u16 value);
std::string ValueToString(u32 value);
std::string ValueToString(float value);
std::string ValueToString(double value);
std::string ValueToString(int value);
std::string ValueToString(bool value);
std::string ValueToString(const std::string& value);
template <typename T>
std::optional<T> TryParse(const std::string& str_value)
{
T value;
if (!::TryParse(str_value, &value))
return std::nullopt;
return value;
}
template <>
inline std::optional<std::string> TryParse(const std::string& str_value)
{
return str_value;
}
}
template <typename T> template <typename T>
struct ConfigInfo; struct ConfigInfo;
using LayerMap = std::map<System, std::vector<std::unique_ptr<Section>>>; class Layer;
using LayerMap = std::map<ConfigLocation, std::optional<std::string>>;
class ConfigLayerLoader class ConfigLayerLoader
{ {
@ -41,32 +70,40 @@ public:
virtual ~Layer(); virtual ~Layer();
// Convenience functions // Convenience functions
bool Exists(System system, const std::string& section_name, const std::string& key); bool Exists(const ConfigLocation& location) const;
bool DeleteKey(System system, const std::string& section_name, const std::string& key); bool DeleteKey(const ConfigLocation& location);
template <typename T> void DeleteAllKeys();
bool GetIfExists(System system, const std::string& section_name, const std::string& key, T* value)
{
if (Exists(system, section_name, key))
return GetOrCreateSection(system, section_name)->Get(key, value);
return false;
}
virtual Section* GetSection(System system, const std::string& section_name);
virtual Section* GetOrCreateSection(System system, const std::string& section_name);
template <typename T> template <typename T>
T Get(const ConfigInfo<T>& config_info) T Get(const ConfigInfo<T>& config_info)
{ {
return GetOrCreateSection(config_info.location.system, config_info.location.section) return Get<T>(config_info.location).value_or(config_info.default_value);
->template Get<T>(config_info.location.key, config_info.default_value); }
template <typename T>
std::optional<T> Get(const ConfigLocation& location)
{
const std::optional<std::string>& str_value = m_map[location];
if (!str_value)
return std::nullopt;
return detail::TryParse<T>(*str_value);
} }
template <typename T> template <typename T>
void Set(const ConfigInfo<T>& config_info, const T& value) void Set(const ConfigInfo<T>& config_info, const T& value)
{ {
GetOrCreateSection(config_info.location.system, config_info.location.section) Set<T>(config_info.location, value);
->Set(config_info.location.key, value); }
template <typename T>
void Set(const ConfigLocation& location, const T& value)
{
const std::string new_value = detail::ValueToString(value);
std::optional<std::string>& current_value = m_map[location];
if (current_value == new_value)
return;
m_is_dirty = true;
current_value = new_value;
} }
// Explicit load and save of layers // Explicit load and save of layers
@ -77,11 +114,9 @@ public:
const LayerMap& GetLayerMap() const; const LayerMap& GetLayerMap() const;
protected: protected:
bool IsDirty() const; bool m_is_dirty = false;
void ClearDirty(); LayerMap m_map;
LayerMap m_sections;
const LayerType m_layer; const LayerType m_layer;
std::unique_ptr<ConfigLayerLoader> m_loader; std::unique_ptr<ConfigLayerLoader> m_loader;
}; };
} // namespace Config }

View File

@ -1,249 +0,0 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstddef>
#include <map>
#include <memory>
#include "Common/Assert.h"
#include "Common/Config/Config.h"
#include "Common/Config/Layer.h"
#include "Common/Config/Section.h"
#include "Common/StringUtil.h"
namespace Config
{
const std::string& Section::NULL_STRING = "";
Section::Section(LayerType layer, System system, const std::string& name)
: m_layer(layer), m_system(system), m_name(name)
{
}
bool Section::Exists(const std::string& key) const
{
return m_values.find(key) != m_values.end();
}
bool Section::Delete(const std::string& key)
{
auto it = m_values.find(key);
if (it == m_values.end())
return false;
m_values.erase(it);
m_deleted_keys.push_back(key);
m_dirty = true;
return true;
}
void Section::Set(const std::string& key, const std::string& value)
{
auto it = m_values.find(key);
if (it != m_values.end() && it->second != value)
{
it->second = value;
m_dirty = true;
}
else if (it == m_values.end())
{
m_values[key] = value;
m_dirty = true;
}
}
void Section::Set(const std::string& key, u16 newValue)
{
Section::Set(key, StringFromFormat("0x%04x", newValue));
}
void Section::Set(const std::string& key, u32 newValue)
{
Section::Set(key, StringFromFormat("0x%08x", newValue));
}
void Section::Set(const std::string& key, float newValue)
{
Section::Set(key, StringFromFormat("%#.9g", newValue));
}
void Section::Set(const std::string& key, double newValue)
{
Section::Set(key, StringFromFormat("%#.17g", newValue));
}
void Section::Set(const std::string& key, int newValue)
{
Section::Set(key, std::to_string(newValue));
}
void Section::Set(const std::string& key, bool newValue)
{
Section::Set(key, StringFromBool(newValue));
}
void Section::Set(const std::string& key, const std::string& newValue,
const std::string& defaultValue)
{
if (newValue != defaultValue)
Set(key, newValue);
else
Delete(key);
}
void Section::SetLines(const std::vector<std::string>& lines)
{
m_lines = lines;
m_dirty = true;
}
bool Section::Get(const std::string& key, std::string* value,
const std::string& default_value) const
{
const auto& it = m_values.find(key);
if (it != m_values.end())
{
*value = it->second;
return true;
}
else if (&default_value != &NULL_STRING)
{
*value = default_value;
return true;
}
return false;
}
bool Section::Get(const std::string& key, int* value, int defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
bool Section::Get(const std::string& key, u16* value, u16 defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
bool Section::Get(const std::string& key, u32* value, u32 defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
bool Section::Get(const std::string& key, bool* value, bool defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
bool Section::Get(const std::string& key, float* value, float defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
bool Section::Get(const std::string& key, double* value, double defaultValue) const
{
std::string temp;
bool retval = Get(key, &temp);
if (retval && TryParse(temp, value))
return true;
*value = defaultValue;
return false;
}
// Return a list of all lines in a section
bool Section::GetLines(std::vector<std::string>* lines, const bool remove_comments) const
{
lines->clear();
for (std::string line : m_lines)
{
line = StripSpaces(line);
if (remove_comments)
{
size_t commentPos = line.find('#');
if (commentPos == 0)
{
continue;
}
if (commentPos != std::string::npos)
{
line = StripSpaces(line.substr(0, commentPos));
}
}
lines->push_back(line);
}
return true;
}
bool Section::HasLines() const
{
return !m_lines.empty();
}
const std::string& Section::GetName() const
{
return m_name;
}
const SectionValueMap& Section::GetValues() const
{
return m_values;
}
const std::vector<std::string>& Section::GetDeletedKeys() const
{
return m_deleted_keys;
}
bool Section::IsDirty() const
{
return m_dirty;
}
void Section::ClearDirty()
{
m_dirty = false;
}
}

View File

@ -1,99 +0,0 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <string>
#include <vector>
// XXX: Purely for case insensitive compare
#include "Common/CommonTypes.h"
#include "Common/Config/Enums.h"
#include "Common/IniFile.h"
namespace Config
{
class Layer;
class ConfigLayerLoader;
using SectionValueMap = std::map<std::string, std::string, CaseInsensitiveStringCompare>;
class Section
{
friend Layer;
friend ConfigLayerLoader;
public:
Section(LayerType layer, System system, const std::string& name);
virtual ~Section() = default;
virtual bool Exists(const std::string& key) const;
bool Delete(const std::string& key);
// Setters
virtual void Set(const std::string& key, const std::string& value);
void Set(const std::string& key, u16 newValue);
void Set(const std::string& key, u32 newValue);
void Set(const std::string& key, float newValue);
void Set(const std::string& key, double newValue);
void Set(const std::string& key, int newValue);
void Set(const std::string& key, bool newValue);
// Setters with default values
void Set(const std::string& key, const std::string& newValue, const std::string& defaultValue);
template <typename T>
void Set(const std::string& key, T newValue, const T defaultValue)
{
if (newValue != defaultValue)
Set(key, newValue);
else
Delete(key);
}
// Getters
virtual bool Get(const std::string& key, std::string* value,
const std::string& default_value = NULL_STRING) const;
bool Get(const std::string& key, int* value, int defaultValue = 0) const;
bool Get(const std::string& key, u16* value, u16 defaultValue = 0) const;
bool Get(const std::string& key, u32* value, u32 defaultValue = 0) const;
bool Get(const std::string& key, bool* value, bool defaultValue = false) const;
bool Get(const std::string& key, float* value, float defaultValue = 0.0f) const;
bool Get(const std::string& key, double* value, double defaultValue = 0.0) const;
template <typename T>
T Get(const std::string& key, const T& default_value) const
{
T value;
Get(key, &value, default_value);
return value;
}
// Section chunk
void SetLines(const std::vector<std::string>& lines);
// XXX: Add to recursive layer
virtual bool GetLines(std::vector<std::string>* lines, const bool remove_comments = true) const;
virtual bool HasLines() const;
const std::string& GetName() const;
const SectionValueMap& GetValues() const;
const std::vector<std::string>& GetDeletedKeys() const;
bool IsDirty() const;
void ClearDirty();
protected:
bool m_dirty = false;
LayerType m_layer;
System m_system;
const std::string m_name;
static const std::string& NULL_STRING;
SectionValueMap m_values;
std::vector<std::string> m_deleted_keys;
std::vector<std::string> m_lines;
};
}

View File

@ -61,6 +61,7 @@ ConfigInfo<bool> GetInfoForSimulateKonga(u32 channel)
} }
const ConfigInfo<bool> MAIN_WII_SD_CARD{{System::Main, "Core", "WiiSDCard"}, false}; const ConfigInfo<bool> MAIN_WII_SD_CARD{{System::Main, "Core", "WiiSDCard"}, false};
const ConfigInfo<bool> MAIN_WII_SD_CARD_WRITABLE{{System::Main, "Core", "WiiSDCardWritable"}, true};
const ConfigInfo<bool> MAIN_WII_KEYBOARD{{System::Main, "Core", "WiiKeyboard"}, false}; const ConfigInfo<bool> MAIN_WII_KEYBOARD{{System::Main, "Core", "WiiKeyboard"}, false};
const ConfigInfo<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING{ const ConfigInfo<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING{
{System::Main, "Core", "WiimoteContinuousScanning"}, false}; {System::Main, "Core", "WiimoteContinuousScanning"}, false};

View File

@ -40,6 +40,7 @@ ConfigInfo<u32> GetInfoForSIDevice(u32 channel);
ConfigInfo<bool> GetInfoForAdapterRumble(u32 channel); ConfigInfo<bool> GetInfoForAdapterRumble(u32 channel);
ConfigInfo<bool> GetInfoForSimulateKonga(u32 channel); ConfigInfo<bool> GetInfoForSimulateKonga(u32 channel);
extern const ConfigInfo<bool> MAIN_WII_SD_CARD; extern const ConfigInfo<bool> MAIN_WII_SD_CARD;
extern const ConfigInfo<bool> MAIN_WII_SD_CARD_WRITABLE;
extern const ConfigInfo<bool> MAIN_WII_KEYBOARD; extern const ConfigInfo<bool> MAIN_WII_KEYBOARD;
extern const ConfigInfo<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING; extern const ConfigInfo<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING;
extern const ConfigInfo<bool> MAIN_WIIMOTE_ENABLE_SPEAKER; extern const ConfigInfo<bool> MAIN_WIIMOTE_ENABLE_SPEAKER;

View File

@ -77,9 +77,9 @@ class BaseConfigLayerLoader final : public Config::ConfigLayerLoader
{ {
public: public:
BaseConfigLayerLoader() : ConfigLayerLoader(Config::LayerType::Base) {} BaseConfigLayerLoader() : ConfigLayerLoader(Config::LayerType::Base) {}
void Load(Config::Layer* config_layer) override void Load(Config::Layer* layer) override
{ {
LoadFromSYSCONF(config_layer); LoadFromSYSCONF(layer);
for (const auto& system : system_to_ini) for (const auto& system : system_to_ini)
{ {
IniFile ini; IniFile ini;
@ -89,55 +89,62 @@ public:
for (const auto& section : system_sections) for (const auto& section : system_sections)
{ {
const std::string section_name = section.GetName(); const std::string section_name = section.GetName();
Config::Section* config_section =
config_layer->GetOrCreateSection(system.first, section_name);
const IniFile::Section::SectionMap& section_map = section.GetValues(); const IniFile::Section::SectionMap& section_map = section.GetValues();
for (const auto& value : section_map) for (const auto& value : section_map)
config_section->Set(value.first, value.second); {
const Config::ConfigLocation location{system.first, section_name, value.first};
layer->Set(location, value.second);
}
} }
} }
} }
void Save(Config::Layer* config_layer) override void Save(Config::Layer* layer) override
{ {
const Config::LayerMap& sections = config_layer->GetLayerMap(); SaveToSYSCONF(layer->GetLayer());
for (const auto& system : sections)
{
if (system.first == Config::System::SYSCONF)
{
SaveToSYSCONF(config_layer->GetLayer());
continue;
}
auto mapping = system_to_ini.find(system.first); std::map<Config::System, IniFile> inis;
if (mapping == system_to_ini.end())
for (const auto& system : system_to_ini)
{
inis[system.first].Load(File::GetUserPath(system.second));
}
for (const auto& config : layer->GetLayerMap())
{
const Config::ConfigLocation& location = config.first;
const std::optional<std::string>& value = config.second;
// Done by SaveToSYSCONF
if (location.system == Config::System::SYSCONF)
continue;
auto ini = inis.find(location.system);
if (ini == inis.end())
{ {
ERROR_LOG(COMMON, "Config can't map system '%s' to an INI file!", ERROR_LOG(COMMON, "Config can't map system '%s' to an INI file!",
Config::GetSystemName(system.first).c_str()); Config::GetSystemName(location.system).c_str());
continue; continue;
} }
IniFile ini; if (!IsSettingSaveable(location))
ini.Load(File::GetUserPath(mapping->second)); continue;
for (const auto& section : system.second) if (value)
{ {
const std::string section_name = section->GetName(); IniFile::Section* ini_section = ini->second.GetOrCreateSection(location.section);
const Config::SectionValueMap& section_values = section->GetValues(); ini_section->Set(location.key, *value);
IniFile::Section* ini_section = ini.GetOrCreateSection(section_name);
for (const auto& value : section_values)
{
if (!IsSettingSaveable({system.first, section->GetName(), value.first}))
continue;
ini_section->Set(value.first, value.second);
}
} }
else
{
ini->second.DeleteKey(location.section, location.key);
}
}
ini.Save(File::GetUserPath(mapping->second)); for (const auto& system : system_to_ini)
{
inis[system.first].Save(File::GetUserPath(system.second));
} }
} }
@ -153,13 +160,10 @@ private:
std::visit( std::visit(
[&](auto& info) { [&](auto& info) {
const std::string key = info.location.section + "." + info.location.key; const std::string key = info.location.section + "." + info.location.key;
auto* section =
layer->GetOrCreateSection(Config::System::SYSCONF, info.location.section);
if (setting.type == SysConf::Entry::Type::Long) if (setting.type == SysConf::Entry::Type::Long)
section->Set(info.location.key, sysconf.GetData<u32>(key, info.default_value)); layer->Set(info.location, sysconf.GetData<u32>(key, info.default_value));
else if (setting.type == SysConf::Entry::Type::Byte) else if (setting.type == SysConf::Entry::Type::Byte)
section->Set(info.location.key, sysconf.GetData<u8>(key, info.default_value)); layer->Set(info.location, sysconf.GetData<u8>(key, info.default_value));
}, },
setting.config_info); setting.config_info);
} }

View File

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

View File

@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "Common/Config/Config.h" #include "Common/Config/Config.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h" #include "Core/Config/SYSCONFSettings.h"
#include "Core/NetPlayProto.h" #include "Core/NetPlayProto.h"
@ -20,29 +21,26 @@ public:
{ {
} }
void Load(Config::Layer* config_layer) override void Load(Config::Layer* layer) override
{ {
Config::Section* core = config_layer->GetOrCreateSection(Config::System::Main, "Core"); layer->Set(Config::MAIN_CPU_THREAD, m_settings.m_CPUthread);
Config::Section* dsp = config_layer->GetOrCreateSection(Config::System::Main, "DSP"); layer->Set(Config::MAIN_CPU_CORE, m_settings.m_CPUcore);
layer->Set(Config::MAIN_GC_LANGUAGE, m_settings.m_SelectedLanguage);
layer->Set(Config::MAIN_OVERRIDE_GC_LANGUAGE, m_settings.m_OverrideGCLanguage);
layer->Set(Config::MAIN_DSP_HLE, m_settings.m_DSPHLE);
layer->Set(Config::MAIN_OVERCLOCK_ENABLE, m_settings.m_OCEnable);
layer->Set(Config::MAIN_OVERCLOCK, m_settings.m_OCFactor);
layer->Set(Config::MAIN_SLOT_A, static_cast<int>(m_settings.m_EXIDevice[0]));
layer->Set(Config::MAIN_SLOT_B, static_cast<int>(m_settings.m_EXIDevice[1]));
layer->Set(Config::MAIN_WII_SD_CARD_WRITABLE, m_settings.m_WriteToMemcard);
core->Set("CPUThread", m_settings.m_CPUthread); layer->Set(Config::MAIN_DSP_JIT, m_settings.m_DSPEnableJIT);
core->Set("CPUCore", m_settings.m_CPUcore);
core->Set("SelectedLanguage", m_settings.m_SelectedLanguage);
core->Set("OverrideGCLang", m_settings.m_OverrideGCLanguage);
core->Set("DSPHLE", m_settings.m_DSPHLE);
core->Set("OverclockEnable", m_settings.m_OCEnable);
core->Set("Overclock", m_settings.m_OCFactor);
core->Set("SlotA", m_settings.m_EXIDevice[0]);
core->Set("SlotB", m_settings.m_EXIDevice[1]);
core->Set("EnableSaving", m_settings.m_WriteToMemcard);
dsp->Set("EnableJIT", m_settings.m_DSPEnableJIT); layer->Set(Config::SYSCONF_PROGRESSIVE_SCAN, m_settings.m_ProgressiveScan);
layer->Set(Config::SYSCONF_PAL60, m_settings.m_PAL60);
config_layer->Set(Config::SYSCONF_PROGRESSIVE_SCAN, m_settings.m_ProgressiveScan);
config_layer->Set(Config::SYSCONF_PAL60, m_settings.m_PAL60);
} }
void Save(Config::Layer* config_layer) override void Save(Config::Layer* layer) override
{ {
// Do Nothing // Do Nothing
} }

View File

@ -45,18 +45,15 @@ public:
} }
} }
void Load(Config::Layer* config_layer) override void Load(Config::Layer* layer) override
{ {
for (auto& value : m_values) for (auto& value : m_values)
{ {
const Config::ConfigLocation location = std::get<0>(value); layer->Set(std::get<0>(value), std::get<1>(value));
Config::Section* section =
config_layer->GetOrCreateSection(location.system, location.section);
section->Set(location.key, std::get<1>(value));
} }
} }
void Save(Config::Layer* config_layer) override void Save(Config::Layer* layer) override
{ {
// Save Nothing // Save Nothing
} }