forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			149 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2016 Dolphin Emulator Project
 | |
| // Licensed under GPLv2+
 | |
| // Refer to the license.txt file included.
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <cstring>
 | |
| #include <map>
 | |
| 
 | |
| #include "Common/Config/Config.h"
 | |
| #include "Common/Config/Layer.h"
 | |
| #include "Common/Config/Section.h"
 | |
| 
 | |
| namespace Config
 | |
| {
 | |
| ConfigLayerLoader::ConfigLayerLoader(LayerType layer) : m_layer(layer)
 | |
| {
 | |
| }
 | |
| 
 | |
| ConfigLayerLoader::~ConfigLayerLoader() = default;
 | |
| 
 | |
| LayerType ConfigLayerLoader::GetLayer() const
 | |
| {
 | |
|   return m_layer;
 | |
| }
 | |
| 
 | |
| Layer::Layer(LayerType type) : m_layer(type)
 | |
| {
 | |
| }
 | |
| 
 | |
| Layer::Layer(std::unique_ptr<ConfigLayerLoader> loader)
 | |
|     : m_layer(loader->GetLayer()), m_loader(std::move(loader))
 | |
| {
 | |
|   Load();
 | |
| }
 | |
| 
 | |
| Layer::~Layer()
 | |
| {
 | |
|   Save();
 | |
| }
 | |
| 
 | |
| bool Layer::Exists(System system, const std::string& section_name, const std::string& key)
 | |
| {
 | |
|   Section* section = GetSection(system, section_name);
 | |
|   if (!section)
 | |
|     return false;
 | |
|   return section->Exists(key);
 | |
| }
 | |
| 
 | |
| bool Layer::DeleteKey(System system, const std::string& section_name, const std::string& key)
 | |
| {
 | |
|   Section* section = GetSection(system, section_name);
 | |
|   if (!section)
 | |
|     return false;
 | |
|   return section->Delete(key);
 | |
| }
 | |
| 
 | |
| Section* Layer::GetSection(System system, const std::string& section_name)
 | |
| {
 | |
|   for (auto& section : m_sections[system])
 | |
|     if (!strcasecmp(section.m_name.c_str(), section_name.c_str()))
 | |
|       return §ion;
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| Section* Layer::GetOrCreateSection(System system, const std::string& section_name)
 | |
| {
 | |
|   Section* section = GetSection(system, section_name);
 | |
|   if (!section)
 | |
|   {
 | |
|     if (m_layer == LayerType::Meta)
 | |
|       m_sections[system].emplace_back(RecursiveSection(m_layer, system, section_name));
 | |
|     else
 | |
|       m_sections[system].emplace_back(Section(m_layer, system, section_name));
 | |
|     section = &m_sections[system].back();
 | |
|   }
 | |
|   return section;
 | |
| }
 | |
| 
 | |
| void Layer::Load()
 | |
| {
 | |
|   if (m_loader)
 | |
|     m_loader->Load(this);
 | |
|   ClearDirty();
 | |
|   InvokeConfigChangedCallbacks();
 | |
| }
 | |
| 
 | |
| void Layer::Save()
 | |
| {
 | |
|   if (!m_loader || !IsDirty())
 | |
|     return;
 | |
| 
 | |
|   m_loader->Save(this);
 | |
|   ClearDirty();
 | |
|   InvokeConfigChangedCallbacks();
 | |
| }
 | |
| 
 | |
| LayerType Layer::GetLayer() const
 | |
| {
 | |
|   return m_layer;
 | |
| }
 | |
| 
 | |
| const LayerMap& Layer::GetLayerMap() const
 | |
| {
 | |
|   return m_sections;
 | |
| }
 | |
| 
 | |
| ConfigLayerLoader* Layer::GetLoader() const
 | |
| {
 | |
|   return m_loader.get();
 | |
| }
 | |
| 
 | |
| 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(); });
 | |
|   });
 | |
| }
 | |
| 
 | |
| RecursiveLayer::RecursiveLayer() : Layer(LayerType::Meta)
 | |
| {
 | |
| }
 | |
| 
 | |
| Section* RecursiveLayer::GetSection(System system, const std::string& section_name)
 | |
| {
 | |
|   // Always queries backwards recursively, so it doesn't matter if it exists or not on this layer
 | |
|   return GetOrCreateSection(system, section_name);
 | |
| }
 | |
| 
 | |
| Section* RecursiveLayer::GetOrCreateSection(System system, const std::string& section_name)
 | |
| {
 | |
|   Section* section = Layer::GetSection(system, section_name);
 | |
|   if (!section)
 | |
|   {
 | |
|     m_sections[system].emplace_back(RecursiveSection(m_layer, system, section_name));
 | |
|     section = &m_sections[system].back();
 | |
|   }
 | |
|   return section;
 | |
| }
 | |
| }
 |