2024-04-01 10:57:04 +00:00
|
|
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
2024-07-30 11:42:36 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0+
|
2022-08-22 13:21:39 +00:00
|
|
|
|
2024-04-01 10:57:04 +00:00
|
|
|
#include "MemorySettingsInterface.h"
|
|
|
|
#include "Error.h"
|
|
|
|
#include "StringUtil.h"
|
2022-08-22 13:21:39 +00:00
|
|
|
|
|
|
|
MemorySettingsInterface::MemorySettingsInterface() = default;
|
|
|
|
|
|
|
|
MemorySettingsInterface::~MemorySettingsInterface() = default;
|
|
|
|
|
2024-04-01 10:57:04 +00:00
|
|
|
bool MemorySettingsInterface::Save(Error* error)
|
2022-08-22 13:21:39 +00:00
|
|
|
{
|
2024-04-01 10:57:04 +00:00
|
|
|
Error::SetStringView(error, "Memory settings cannot be saved.");
|
2022-08-22 13:21:39 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::Clear()
|
|
|
|
{
|
|
|
|
m_sections.clear();
|
|
|
|
}
|
|
|
|
|
2024-05-04 13:33:35 +00:00
|
|
|
bool MemorySettingsInterface::IsEmpty()
|
|
|
|
{
|
|
|
|
return m_sections.empty();
|
|
|
|
}
|
|
|
|
|
2022-08-22 13:21:39 +00:00
|
|
|
bool MemorySettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto iter = sit->second.find(key);
|
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::optional<s32> parsed = StringUtil::FromChars<s32>(iter->second, 10);
|
|
|
|
if (!parsed.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = parsed.value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key, u32* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto iter = sit->second.find(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::optional<u32> parsed = StringUtil::FromChars<u32>(iter->second, 10);
|
|
|
|
if (!parsed.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = parsed.value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto iter = sit->second.find(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::optional<float> parsed = StringUtil::FromChars<float>(iter->second);
|
|
|
|
if (!parsed.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = parsed.value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto iter = sit->second.find(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::optional<double> parsed = StringUtil::FromChars<double>(iter->second);
|
|
|
|
if (!parsed.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = parsed.value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto iter = sit->second.find(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::optional<bool> parsed = StringUtil::FromChars<bool>(iter->second);
|
|
|
|
if (!parsed.has_value())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = parsed.value();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto iter = sit->second.find(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = iter->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-12 13:39:43 +00:00
|
|
|
bool MemorySettingsInterface::GetStringValue(const char* section, const char* key, SmallStringBase* value) const
|
|
|
|
{
|
|
|
|
const auto sit = m_sections.find(section);
|
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const auto iter = sit->second.find(key);
|
|
|
|
if (iter == sit->second.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
value->assign(iter->second);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-08-22 13:21:39 +00:00
|
|
|
void MemorySettingsInterface::SetIntValue(const char* section, const char* key, s32 value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetUIntValue(const char* section, const char* key, u32 value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetFloatValue(const char* section, const char* key, float value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetDoubleValue(const char* section, const char* key, double value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetBoolValue(const char* section, const char* key, bool value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetStringValue(const char* section, const char* key, const char* value)
|
|
|
|
{
|
|
|
|
SetValue(section, key, value);
|
|
|
|
}
|
|
|
|
|
2022-12-21 12:38:31 +00:00
|
|
|
std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKeyValueList(const char* section) const
|
|
|
|
{
|
|
|
|
std::vector<std::pair<std::string, std::string>> output;
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-12-21 12:38:31 +00:00
|
|
|
if (sit != m_sections.end())
|
|
|
|
{
|
|
|
|
for (const auto& it : sit->second)
|
|
|
|
output.emplace_back(it.first, it.second);
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetKeyValueList(const char* section, const std::vector<std::pair<std::string, std::string>>& items)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-12-21 12:38:31 +00:00
|
|
|
sit->second.clear();
|
|
|
|
for (const auto& [key, value] : items)
|
|
|
|
sit->second.emplace(key, value);
|
|
|
|
}
|
|
|
|
|
2022-08-22 13:21:39 +00:00
|
|
|
void MemorySettingsInterface::SetValue(const char* section, const char* key, std::string value)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (range.first == sit->second.end())
|
|
|
|
{
|
|
|
|
sit->second.emplace(std::string(key), std::move(value));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto iter = range.first;
|
|
|
|
iter->second = std::move(value);
|
|
|
|
++iter;
|
|
|
|
|
|
|
|
// remove other values
|
|
|
|
while (iter != range.second)
|
|
|
|
{
|
|
|
|
auto remove = iter++;
|
|
|
|
sit->second.erase(remove);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> MemorySettingsInterface::GetStringList(const char* section, const char* key) const
|
|
|
|
{
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit != m_sections.end())
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
for (auto iter = range.first; iter != range.second; ++iter)
|
|
|
|
ret.emplace_back(iter->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::SetStringList(const char* section, const char* key, const std::vector<std::string>& items)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
for (auto iter = range.first; iter != range.second;)
|
|
|
|
sit->second.erase(iter++);
|
|
|
|
|
|
|
|
std::string_view keysv(key);
|
|
|
|
for (const std::string& value : items)
|
|
|
|
sit->second.emplace(keysv, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
bool result = false;
|
|
|
|
for (auto iter = range.first; iter != range.second;)
|
|
|
|
{
|
|
|
|
if (iter->second == item)
|
|
|
|
{
|
|
|
|
sit->second.erase(iter++);
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
for (auto iter = range.first; iter != range.second; ++iter)
|
|
|
|
{
|
|
|
|
if (iter->second == item)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sit->second.emplace(std::string(key), std::string(item));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemorySettingsInterface::ContainsValue(const char* section, const char* key) const
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return (sit->second.find(key) != sit->second.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::DeleteValue(const char* section, const char* key)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return;
|
|
|
|
|
2023-07-22 03:15:26 +00:00
|
|
|
const auto range = sit->second.equal_range(key);
|
2022-08-22 13:21:39 +00:00
|
|
|
for (auto iter = range.first; iter != range.second;)
|
|
|
|
sit->second.erase(iter++);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::ClearSection(const char* section)
|
|
|
|
{
|
2023-07-22 03:15:26 +00:00
|
|
|
auto sit = m_sections.find(section);
|
2022-08-22 13:21:39 +00:00
|
|
|
if (sit == m_sections.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_sections.erase(sit);
|
|
|
|
}
|
2024-05-04 13:33:35 +00:00
|
|
|
|
|
|
|
void MemorySettingsInterface::RemoveSection(const char* section)
|
|
|
|
{
|
|
|
|
auto sit = m_sections.find(section);
|
|
|
|
if (sit == m_sections.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_sections.erase(sit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemorySettingsInterface::RemoveEmptySections()
|
|
|
|
{
|
|
|
|
for (auto sit = m_sections.begin(); sit != m_sections.end();)
|
|
|
|
{
|
|
|
|
if (sit->second.size() > 0)
|
|
|
|
{
|
|
|
|
++sit;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
sit = m_sections.erase(sit);
|
|
|
|
}
|
|
|
|
}
|