summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Src/IniFile.cpp
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2010-06-04 19:56:34 +0000
committerhrydgard <hrydgard@gmail.com>2010-06-04 19:56:34 +0000
commit05c418ebe2da24a8df4ef2c1d1d7864eb2d806e3 (patch)
tree0a8dd75e6505458ca28eb4066fd0887645dd5ea6 /Source/Core/Common/Src/IniFile.cpp
parent1435c2527add244b7e1590b20e1e4db56b9e0108 (diff)
Refactor the original and much more compatible IniFile implementation to work more like Billiard's, with a public Section interface, but keep the old interface as well.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5603 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/Common/Src/IniFile.cpp')
-rw-r--r--Source/Core/Common/Src/IniFile.cpp434
1 files changed, 216 insertions, 218 deletions
diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp
index 04f08168a9..84f5a099d1 100644
--- a/Source/Core/Common/Src/IniFile.cpp
+++ b/Source/Core/Common/Src/IniFile.cpp
@@ -28,167 +28,273 @@
#include "StringUtil.h"
#include "IniFile.h"
-IniFile::IniFile()
-{}
+namespace {
-IniFile::~IniFile()
-{}
+static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut)
+{
+ //
+ int FirstEquals = (int)line.find("=", 0);
+ int FirstCommentChar = -1;
+ // Comments
+ //if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find(";", FirstEquals > 0 ? FirstEquals : 0);}
+ if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("#", FirstEquals > 0 ? FirstEquals : 0);}
+ if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("//", FirstEquals > 0 ? FirstEquals : 0);}
+
+ // Allow preservation of spacing before comment
+ if (FirstCommentChar > 0)
+ {
+ while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab
+ {
+ FirstCommentChar--;
+ }
+ }
+
+ if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar)))
+ {
+ // Yes, a valid line!
+ *keyOut = StripSpaces(line.substr(0, FirstEquals));
+ if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string("");
+ if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1)));
+ }
+}
-Section::Section()
+}
+
+IniFile::Section::Section()
: lines(), name(""), comment("") {}
-Section::Section(const std::string& _name)
+IniFile::Section::Section(const std::string& _name)
: lines(), name(_name), comment("") {}
-Section::Section(const Section& other)
+IniFile::Section::Section(const Section& other)
{
name = other.name;
comment = other.comment;
lines = other.lines;
}
-const Section* IniFile::GetSection(const char* sectionName) const
+std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut)
{
- for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
- if (!strcasecmp(iter->name.c_str(), sectionName))
- return (&(*iter));
+ for (std::vector<std::string>::iterator iter = lines.begin(); iter != lines.end(); ++iter)
+ {
+ std::string& line = *iter;
+ std::string lineKey;
+ ParseLine(line, &lineKey, valueOut, commentOut);
+ if (!strcasecmp(lineKey.c_str(), key))
+ return &line;
+ }
return 0;
}
-Section* IniFile::GetSection(const char* sectionName)
+void IniFile::Section::Set(const char* key, const char* newValue)
{
- for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
- if (!strcasecmp(iter->name.c_str(), sectionName))
- return (&(*iter));
- return 0;
+ std::string value, comment;
+ std::string* line = GetLine(key, &value, &comment);
+ if (line)
+ {
+ // Change the value - keep the key and comment
+ *line = StripSpaces(key) + " = " + newValue + comment;
+ }
+ else
+ {
+ // The key did not already exist in this section - let's add it.
+ lines.push_back(std::string(key) + " = " + newValue);
+ }
}
-Section* IniFile::GetOrCreateSection(const char* sectionName)
+bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue)
{
- Section* section = GetSection(sectionName);
-
- if (!section)
+ std::string* line = GetLine(key, value, 0);
+ if (!line)
{
- sections.push_back(Section(sectionName));
- section = &sections[sections.size() - 1];
+ if (defaultValue)
+ {
+ *value = defaultValue;
+ }
+ return false;
}
-
- return(section);
+ return true;
}
-
-bool IniFile::DeleteSection(const char* sectionName)
+void IniFile::Section::Set(const char* key, const std::vector<std::string>& newValues)
{
- Section* s = GetSection(sectionName);
-
- if (!s)
+ std::string temp;
+ // Join the strings with ,
+ std::vector<std::string>::const_iterator it;
+ for (it = newValues.begin(); it != newValues.end(); ++it)
{
- return false;
+ temp = (*it) + ",";
}
+ // remove last ,
+ temp.resize(temp.length() - 1);
+ Set(key, temp.c_str());
+}
- for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
+bool IniFile::Section::Get(const char* key, std::vector<std::string>& values)
+{
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (!retval || temp.empty())
{
- if (&(*iter) == s)
- {
- sections.erase(iter);
- return true;
- }
+ return false;
}
+ // ignore starting , if any
+ size_t subStart = temp.find_first_not_of(",");
+ size_t subEnd;
+
+ // split by ,
+ while (subStart != std::string::npos) {
+
+ // Find next ,
+ subEnd = temp.find_first_of(",", subStart);
+ if (subStart != subEnd)
+ // take from first char until next ,
+ values.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart)));
+
+ // Find the next non , char
+ subStart = temp.find_first_not_of(",", subEnd);
+ }
+
+ return true;
+}
+bool IniFile::Section::Get(const char* key, int* value, int defaultValue)
+{
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (retval && TryParseInt(temp.c_str(), value))
+ return true;
+ *value = defaultValue;
return false;
}
-void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) const
+bool IniFile::Section::Get(const char* key, u32* value, u32 defaultValue)
{
- //
- int FirstEquals = (int)line.find("=", 0);
- int FirstCommentChar = -1;
- // Comments
- //if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find(";", FirstEquals > 0 ? FirstEquals : 0);}
- if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("#", FirstEquals > 0 ? FirstEquals : 0);}
- if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("//", FirstEquals > 0 ? FirstEquals : 0);}
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (retval && TryParseUInt(temp.c_str(), value))
+ return true;
+ *value = defaultValue;
+ return false;
+}
- // Allow preservation of spacing before comment
- if (FirstCommentChar > 0)
- {
- while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab
- {
- FirstCommentChar--;
- }
- }
+bool IniFile::Section::Get(const char* key, bool* value, bool defaultValue)
+{
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (retval && TryParseBool(temp.c_str(), value))
+ return true;
+ *value = defaultValue;
+ return false;
+}
- if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar)))
- {
- // Yes, a valid line!
- *keyOut = StripSpaces(line.substr(0, FirstEquals));
- if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string("");
- if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1)));
- }
+bool IniFile::Section::Get(const char* key, float* value, float defaultValue)
+{
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (retval && TryParseFloat(temp.c_str(), value))
+ return true;
+ *value = defaultValue;
+ return false;
+}
+
+bool IniFile::Section::Get(const char* key, double* value, double defaultValue)
+{
+ std::string temp;
+ bool retval = Get(key, &temp, 0);
+ if (retval && TryParseDouble(temp.c_str(), value))
+ return true;
+ *value = defaultValue;
+ return false;
}
-std::string* IniFile::GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut)
+bool IniFile::Section::Exists(const char *key) const
{
- for (std::vector<std::string>::iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
+ for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
- std::string& line = *iter;
std::string lineKey;
- ParseLine(line, &lineKey, valueOut, commentOut);
-
+ ParseLine(*iter, &lineKey, NULL, NULL);
if (!strcasecmp(lineKey.c_str(), key))
- {
- return &line;
- }
+ return true;
}
+ return false;
+}
+
+// IniFile
+
+IniFile::IniFile() {}
+IniFile::~IniFile() {}
+
+const IniFile::Section* IniFile::GetSection(const char* sectionName) const
+{
+ for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
+ if (!strcasecmp(iter->name.c_str(), sectionName))
+ return (&(*iter));
return 0;
}
-bool IniFile::Exists(const char* const sectionName, const char* key) const
+IniFile::Section* IniFile::GetSection(const char* sectionName)
{
+ for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
+ if (!strcasecmp(iter->name.c_str(), sectionName))
+ return (&(*iter));
+ return 0;
+}
- const Section* const section = GetSection(sectionName);
+IniFile::Section* IniFile::GetOrCreateSection(const char* sectionName)
+{
+ Section* section = GetSection(sectionName);
if (!section)
- return false;
-
- for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
{
- std::string lineKey;
- ParseLine(*iter, &lineKey, NULL, NULL);
+ sections.push_back(Section(sectionName));
+ section = &sections[sections.size() - 1];
+ }
+ return section;
+}
- if (!strcasecmp(lineKey.c_str(), key))
+bool IniFile::DeleteSection(const char* sectionName)
+{
+ Section* s = GetSection(sectionName);
+ if (!s)
+ return false;
+ for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
+ {
+ if (&(*iter) == s)
{
+ sections.erase(iter);
return true;
}
}
-
return false;
}
+bool IniFile::Exists(const char* sectionName, const char* key) const
+{
+ const Section* section = GetSection(sectionName);
+ if (!section)
+ return false;
+ return section->Exists(key);
+}
+
void IniFile::SetLines(const char* sectionName, const std::vector<std::string> &lines)
{
Section* section = GetOrCreateSection(sectionName);
section->lines.clear();
-
for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
{
section->lines.push_back(*iter);
}
}
-
bool IniFile::DeleteKey(const char* sectionName, const char* key)
{
Section* section = GetSection(sectionName);
-
if (!section)
- {
return false;
- }
-
- std::string* line = GetLine(section, key, 0, 0);
-
+ std::string* line = section->GetLine(key, 0, 0);
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
if (line == &(*liter))
@@ -197,7 +303,6 @@ bool IniFile::DeleteKey(const char* sectionName, const char* key)
return true;
}
}
-
return false; //shouldn't happen
}
@@ -205,21 +310,15 @@ bool IniFile::DeleteKey(const char* sectionName, const char* key)
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) const
{
const Section* section = GetSection(sectionName);
-
if (!section)
- {
return false;
- }
-
keys.clear();
-
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
{
std::string key;
ParseLine(*liter, &key, 0, 0);
keys.push_back(key);
}
-
return true;
}
@@ -347,163 +446,62 @@ bool IniFile::Save(const char* filename)
return true;
}
-void IniFile::Set(const char* sectionName, const char* key, const char* newValue)
-{
- Section* section = GetOrCreateSection(sectionName);
- std::string value, comment;
- std::string* line = GetLine(section, key, &value, &comment);
-
- if (line)
- {
- // Change the value - keep the key and comment
- *line = StripSpaces(key) + " = " + newValue + comment;
- }
- else
- {
- // The key did not already exist in this section - let's add it.
- section->lines.push_back(std::string(key) + " = " + newValue);
- }
-}
-
-void IniFile::Set(const char* sectionName, const char* key, const std::vector<std::string>& newValues)
-{
- std::string temp;
-
- // Join the strings with ,
- std::vector<std::string>::const_iterator it;
- for (it = newValues.begin(); it != newValues.end(); ++it) {
-
- temp = (*it) + ",";
- }
-
- // remove last ,
- temp.resize(temp.length() - 1);
-
- Set(sectionName, key, temp.c_str());
-}
-
-void IniFile::Set(const char* sectionName, const char* key, u32 newValue)
-{
- Set(sectionName, key, StringFromFormat("0x%08x", newValue).c_str());
-}
-
-
-void IniFile::Set(const char* sectionName, const char* key, int newValue)
-{
- Set(sectionName, key, StringFromInt(newValue).c_str());
-}
-
-
-void IniFile::Set(const char* sectionName, const char* key, bool newValue)
-{
- Set(sectionName, key, StringFromBool(newValue).c_str());
-}
bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue)
{
Section* section = GetSection(sectionName);
-
- if (!section)
- {
- if (defaultValue)
- {
- *value = defaultValue;
- }
- return false;
- }
-
- std::string* line = GetLine(section, key, value, 0);
-
- if (!line)
- {
- if (defaultValue)
- {
+ if (!section) {
+ if (defaultValue) {
*value = defaultValue;
}
return false;
}
-
- return true;
+ return section->Get(key, value, defaultValue);
}
-
-bool IniFile::Get(const char* sectionName, const char* key, std::vector<std::string>& values)
+bool IniFile::Get(const char *sectionName, const char* key, std::vector<std::string>& values)
{
-
- std::string temp;
- bool retval = Get(sectionName, key, &temp, 0);
-
- if (! retval || temp.empty()) {
+ Section *section = GetSection(sectionName);
+ if (!section)
return false;
- }
-
-
- // ignore starting , if any
- size_t subStart = temp.find_first_not_of(",");
- size_t subEnd;
-
- // split by ,
- while (subStart != std::string::npos) {
-
- // Find next ,
- subEnd = temp.find_first_of(",", subStart);
- if (subStart != subEnd)
- // take from first char until next ,
- values.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart)));
-
- // Find the next non , char
- subStart = temp.find_first_not_of(",", subEnd);
- }
-
- return true;
+ return section->Get(key, values);
}
bool IniFile::Get(const char* sectionName, const char* key, int* value, int defaultValue)
{
- std::string temp;
- bool retval = Get(sectionName, key, &temp, 0);
-
- if (retval && TryParseInt(temp.c_str(), value))
- {
- return true;
+ Section *section = GetSection(sectionName);
+ if (!section) {
+ *value = defaultValue;
+ return false;
+ } else {
+ return section->Get(key, value, defaultValue);
}
-
- *value = defaultValue;
- return false;
}
-
bool IniFile::Get(const char* sectionName, const char* key, u32* value, u32 defaultValue)
{
- std::string temp;
- bool retval = Get(sectionName, key, &temp, 0);
-
- if (retval && TryParseUInt(temp.c_str(), value))
- {
- return true;
+ Section *section = GetSection(sectionName);
+ if (!section) {
+ *value = defaultValue;
+ return false;
+ } else {
+ return section->Get(key, value, defaultValue);
}
-
- *value = defaultValue;
- return false;
}
-
bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool defaultValue)
{
- std::string temp;
- bool retval = Get(sectionName, key, &temp, 0);
-
- if (retval && TryParseBool(temp.c_str(), value))
- {
- return true;
+ Section *section = GetSection(sectionName);
+ if (!section) {
+ *value = defaultValue;
+ return false;
+ } else {
+ return section->Get(key, value, defaultValue);
}
-
- *value = defaultValue;
- return false;
}
-// TODO: Keep this code below?
+// Unit test. TODO: Move to the real unit test framework.
/*
int main()
{