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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								}
							 |