dolphin/Source/Core/Common/Config.h
Léo Lam abe6f8766a Config: Add a few helper functions for repetitive tasks
Getting and setting configuration from the base config layer are common
and repetitive tasks. This commit adds some simpler to use functions to
make the new system easier to work with.

Config::Get and Config::Set are intended to make switching from
SConfig a bit less painful. They always operate on the main system.

Example usage:

    // before
    auto base_layer = Config::GetLayer(Config::LayerType::Base);
    auto core = base_layer->GetOrCreateSection(Config::System::Main, "Core");
    u8 language;
    core->Get("Language", &language, 0);
    SetData("IPL.LNG", language);

    // now
    auto base_layer = Config::GetLayer(Config::LayerType::Base);
    auto core = base_layer->GetOrCreateSection(Config::System::Main, "Core");
    SetData("IPL.LNG", core->Get<u8>("Language", 0));

    // or simply
    SetData("IPL.LNG", Config::Get<u8>("Core", "Language", 0));
2017-02-23 18:15:12 +01:00

220 lines
6.1 KiB
C++

// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <list>
#include <map>
#include <memory>
#include <string>
// XXX: Purely for case insensitive compare
#include "Common/IniFile.h"
namespace Config
{
enum class LayerType
{
Base,
GlobalGame,
LocalGame,
Movie,
Netplay,
CommandLine,
CurrentRun,
Meta,
};
enum class System
{
Main,
GCPad,
WiiPad,
GCKeyboard,
GFX,
Logger,
Debugger,
UI,
};
class Section;
class Layer;
class ConfigLayerLoader;
using SectionValueMap = std::map<std::string, std::string, CaseInsensitiveStringCompare>;
using LayerMap = std::map<System, std::list<Section*>>;
using Layers = std::map<LayerType, std::unique_ptr<Layer>>;
using ConfigChangedCallback = std::function<void()>;
class Section
{
friend Layer;
friend ConfigLayerLoader;
public:
Section(LayerType layer, System system, const std::string& name)
: m_layer(layer), m_system(system), m_name(name)
{
}
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, 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, 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 { return m_lines.size() > 0; }
const std::string& GetName() const { return m_name; }
const SectionValueMap& GetValues() const { return m_values; }
const std::vector<std::string>& GetDeletedKeys() const { return m_deleted_keys; }
bool IsDirty() const { return m_dirty; }
void ClearDirty() { m_dirty = false; }
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;
};
// XXX: Allow easy migration!
class ConfigLayerLoader
{
public:
ConfigLayerLoader(LayerType layer) : m_layer(layer) {}
~ConfigLayerLoader() {}
virtual void Load(Layer* config_layer) = 0;
virtual void Save(Layer* config_layer) = 0;
LayerType GetLayer() const { return m_layer; }
private:
const LayerType m_layer;
};
class Layer
{
public:
explicit Layer(LayerType layer) : m_layer(layer) {}
Layer(std::unique_ptr<ConfigLayerLoader> loader);
virtual ~Layer();
// Convenience functions
bool Exists(System system, const std::string& section_name, const std::string& key);
bool DeleteKey(System system, const std::string& section_name, const std::string& key);
template <typename T>
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);
// Explicit load and save of layers
void Load();
void Save();
LayerType GetLayer() const { return m_layer; }
const LayerMap& GetLayerMap() { return m_sections; }
// Stay away from this routine as much as possible
ConfigLayerLoader* GetLoader() { return m_loader.get(); }
protected:
bool IsDirty() const;
void ClearDirty();
LayerMap m_sections;
const LayerType m_layer;
std::unique_ptr<ConfigLayerLoader> m_loader;
};
// Common function used for getting configuration
Section* GetOrCreateSection(System system, const std::string& section_name);
// Layer management
Layers* GetLayers();
void AddLayer(std::unique_ptr<Layer> layer);
void AddLayer(std::unique_ptr<ConfigLayerLoader> loader);
void AddLoadLayer(std::unique_ptr<Layer> layer);
void AddLoadLayer(std::unique_ptr<ConfigLayerLoader> loader);
Layer* GetLayer(LayerType layer);
void RemoveLayer(LayerType layer);
bool LayerExists(LayerType layer);
void AddConfigChangedCallback(ConfigChangedCallback func);
// Explicit load and save of layers
void Load();
void Save();
// Often used functions for getting or setting configuration on the base layer for the main system
template <typename T>
T Get(const std::string& section_name, const std::string& key, const T& default_value)
{
auto base_layer = GetLayer(Config::LayerType::Base);
return base_layer->GetOrCreateSection(Config::System::Main, section_name)
->Get(key, default_value);
}
template <typename T>
void Set(const std::string& section_name, const std::string& key, const T& value)
{
auto base_layer = GetLayer(Config::LayerType::Base);
base_layer->GetOrCreateSection(Config::System::Main, section_name)->Set(key, value);
}
void Init();
void Shutdown();
const std::string& GetSystemName(System system);
System GetSystemFromName(const std::string& system);
const std::string& GetLayerName(LayerType layer);
}