forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			297 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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;
 | |
| }
 | |
| 
 | |
| RecursiveSection::RecursiveSection(LayerType layer, System system, const std::string& name)
 | |
|     : Section(layer, system, name)
 | |
| {
 | |
| }
 | |
| 
 | |
| bool RecursiveSection::Exists(const std::string& key) const
 | |
| {
 | |
|   auto layers_it = Config::GetLayers()->find(LayerType::Meta);
 | |
|   do
 | |
|   {
 | |
|     const Section* layer_section = layers_it->second->GetSection(m_system, m_name);
 | |
|     if (layer_section && layer_section->Exists(key))
 | |
|     {
 | |
|       return true;
 | |
|     }
 | |
|   } while (--layers_it != Config::GetLayers()->end());
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool RecursiveSection::Get(const std::string& key, std::string* value,
 | |
|                            const std::string& default_value) const
 | |
| {
 | |
|   for (auto layer_id : SEARCH_ORDER)
 | |
|   {
 | |
|     auto layers_it = Config::GetLayers()->find(layer_id);
 | |
|     if (layers_it == Config::GetLayers()->end())
 | |
|       continue;
 | |
| 
 | |
|     const Section* layer_section = layers_it->second->GetSection(m_system, m_name);
 | |
|     if (layer_section && layer_section->Exists(key))
 | |
|     {
 | |
|       return layer_section->Get(key, value, default_value);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Section::Get(key, value, default_value);
 | |
| }
 | |
| 
 | |
| void RecursiveSection::Set(const std::string& key, const std::string& value)
 | |
| {
 | |
|   // The RecursiveSection can't set since it is used to recursively get values from the layer
 | |
|   // map.
 | |
|   // It is only a part of the meta layer, and the meta layer isn't allowed to set any values.
 | |
|   _assert_msg_(COMMON, false, "Don't try to set values here!");
 | |
| }
 | |
| }
 |