mkxp/src/iniconfig.cpp
2019-03-19 19:26:50 +01:00

114 lines
2.4 KiB
C++

#include "iniconfig.h"
#include <algorithm>
std::string toLowerCase(const std::string& str)
{
std::string lower = str;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower;
}
std::string trim(const std::string& str, const std::string& chars = "\t\n\v\f\r ")
{
std::string trimmed = str;
trimmed.erase(trimmed.find_last_not_of(chars) + 1);
trimmed.erase(0, trimmed.find_first_not_of(chars));
return trimmed;
}
INIConfiguration::Section::Section (const std::string& sname) : m_Name (sname), m_PropertyMap()
{
}
bool INIConfiguration::Section::getStringProperty (const std::string& name, std::string& outPropStr) const
{
try
{
outPropStr = m_PropertyMap.at(toLowerCase(name)).m_Value;
return true;
}
catch (std::out_of_range& oorexcept)
{
return false;
}
}
bool INIConfiguration::load (std::istream& is)
{
if (!is.good())
{
return false;
}
std::string currSectionName;
std::string line;
std::getline (is, line);
while (!is.eof() && !is.bad())
{
if (line[0] == '[')
{
currSectionName = line.substr (1, line.find_last_of (']') - 1);
}
else if (line[0] != '#' && line.length() > 2)
{
int crloc = line.length() - 1;
if (crloc >= 0 && line[crloc] == '\r') //check for Windows-style newline
line.resize (crloc); //and correct
size_t equalsPos = line.find_first_of ("=");
if (equalsPos != std::string::npos)
{
std::string key = line.substr (0, equalsPos);
std::string val = line.substr (equalsPos + 1);
addProperty (currSectionName, key , val);
}
}
std::getline (is, line);
}
if (is.bad())
{
return false;
}
return true;
}
std::string INIConfiguration::getStringProperty(const std::string& sname, const std::string& name, const std::string& def) const
{
auto sectionIt = m_SectionMap.find(toLowerCase(sname));
if (sectionIt != m_SectionMap.end())
{
std::string prop;
if(sectionIt->second.getStringProperty(name, prop))
{
return prop;
}
}
return def;
}
void INIConfiguration::addProperty (const std::string& sname, const std::string& name, const std::string& val)
{
if (m_SectionMap.find (toLowerCase(sname)) == m_SectionMap.end())
{
m_SectionMap.emplace (toLowerCase(sname), Section (sname));
}
Section::Property p;
p.m_Name = trim(name);
p.m_Value = trim(val);
m_SectionMap.at (toLowerCase(sname)).m_PropertyMap[toLowerCase(p.m_Name)] = p;
}