summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Src/IniFile.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2013-09-14 19:24:27 +0200
committerPierre Bourdon <delroth@gmail.com>2013-09-14 19:24:27 +0200
commit24e9aedc1420d1947f1a7bf5b57ddbab3c5fb2dd (patch)
treee8800ed5ed9a693cbb5310c7b57f321c15d28329 /Source/Core/Common/Src/IniFile.cpp
parente56071f2be777e0fb9b362c0c3e73144eca4191e (diff)
parent4ef5624f1fd46f3d4dd59b98f9c6c485f0dfd566 (diff)
Merge branch 'global-user-directory'
Please read https://wiki.dolphin-emu.org/index.php?title=Controlling_the_Global_User_Directory for documentation about this feature. Thanks to neobrain and RachelB for their work on this change, and thanks to everyone who helped test it.
Diffstat (limited to 'Source/Core/Common/Src/IniFile.cpp')
-rw-r--r--Source/Core/Common/Src/IniFile.cpp167
1 files changed, 72 insertions, 95 deletions
diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp
index 2eca8df929..1c45a8095e 100644
--- a/Source/Core/Common/Src/IniFile.cpp
+++ b/Source/Core/Common/Src/IniFile.cpp
@@ -20,7 +20,7 @@
namespace {
-static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
+void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
{
if (line[0] == '#')
return;
@@ -37,32 +37,15 @@ static void ParseLine(const std::string& line, std::string* keyOut, std::string*
}
-std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut)
-{
- for (std::vector<std::string>::iterator iter = lines.begin(); iter != lines.end(); ++iter)
- {
- std::string& line = *iter;
- std::string lineKey;
- ParseLine(line, &lineKey, valueOut);
- if (!strcasecmp(lineKey.c_str(), key))
- return &line;
- }
- return 0;
-}
-
void IniFile::Section::Set(const char* key, const char* newValue)
{
- std::string value;
- std::string* line = GetLine(key, &value);
- if (line)
- {
- // Change the value - keep the key and comment
- *line = StripSpaces(key) + " = " + newValue;
- }
+ auto it = values.find(key);
+ if (it != values.end())
+ it->second = newValue;
else
{
- // The key did not already exist in this section - let's add it.
- lines.push_back(std::string(key) + " = " + newValue);
+ values[key] = newValue;
+ keys_order.push_back(key);
}
}
@@ -74,20 +57,6 @@ void IniFile::Section::Set(const char* key, const std::string& newValue, const s
Delete(key);
}
-bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue)
-{
- std::string* line = GetLine(key, value);
- if (!line)
- {
- if (defaultValue)
- {
- *value = defaultValue;
- }
- return false;
- }
- return true;
-}
-
void IniFile::Section::Set(const char* key, const float newValue, const float defaultValue)
{
if (newValue != defaultValue)
@@ -126,7 +95,24 @@ void IniFile::Section::Set(const char* key, const std::vector<std::string>& newV
Set(key, temp.c_str());
}
-bool IniFile::Section::Get(const char* key, std::vector<std::string>& values)
+bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue)
+{
+ auto it = values.find(key);
+ if (it != values.end())
+ {
+ *value = it->second;
+ return true;
+ }
+ else if (defaultValue)
+ {
+ *value = defaultValue;
+ return true;
+ }
+ else
+ return false;
+}
+
+bool IniFile::Section::Get(const char* key, std::vector<std::string>& out)
{
std::string temp;
bool retval = Get(key, &temp, 0);
@@ -145,7 +131,7 @@ bool IniFile::Section::Get(const char* key, std::vector<std::string>& values)
subEnd = temp.find_first_of(",", subStart);
if (subStart != subEnd)
// take from first char until next ,
- values.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart)));
+ out.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart)));
// Find the next non , char
subStart = temp.find_first_not_of(",", subEnd);
@@ -206,28 +192,18 @@ bool IniFile::Section::Get(const char* key, double* value, double defaultValue)
bool IniFile::Section::Exists(const char *key) const
{
- for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
- {
- std::string lineKey;
- ParseLine(*iter, &lineKey, NULL);
- if (!strcasecmp(lineKey.c_str(), key))
- return true;
- }
- return false;
+ return values.find(key) != values.end();
}
bool IniFile::Section::Delete(const char *key)
{
- std::string* line = GetLine(key, 0);
- for (std::vector<std::string>::iterator liter = lines.begin(); liter != lines.end(); ++liter)
- {
- if (line == &*liter)
- {
- lines.erase(liter);
- return true;
- }
- }
- return false;
+ auto it = values.find(key);
+ if (it == values.end())
+ return false;
+
+ values.erase(it);
+ keys_order.erase(std::find(keys_order.begin(), keys_order.end(), key));
+ return true;
}
// IniFile
@@ -286,11 +262,7 @@ bool IniFile::Exists(const char* sectionName, const char* key) const
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);
- }
+ section->lines = lines;
}
bool IniFile::DeleteKey(const char* sectionName, const char* key)
@@ -298,16 +270,7 @@ bool IniFile::DeleteKey(const char* sectionName, const char* key)
Section* section = GetSection(sectionName);
if (!section)
return false;
- std::string* line = section->GetLine(key, 0);
- for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
- {
- if (line == &(*liter))
- {
- section->lines.erase(liter);
- return true;
- }
- }
- return false; //shouldn't happen
+ return section->Delete(key);
}
// Return a list of all keys in a section
@@ -316,13 +279,7 @@ bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) c
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);
- keys.push_back(key);
- }
+ keys = section->keys_order;
return true;
}
@@ -364,13 +321,13 @@ void IniFile::SortSections()
std::sort(sections.begin(), sections.end());
}
-bool IniFile::Load(const char* filename)
+bool IniFile::Load(const char* filename, bool keep_current_data)
{
// Maximum number of letters in a line
static const int MAX_BYTES = 1024*32;
- sections.clear();
- sections.push_back(Section(""));
+ if (!keep_current_data)
+ sections.clear();
// first section consists of the comments before the first real section
// Open file
@@ -379,12 +336,13 @@ bool IniFile::Load(const char* filename)
if (in.fail()) return false;
+ Section* current_section = NULL;
while (!in.eof())
{
char templine[MAX_BYTES];
in.getline(templine, MAX_BYTES);
std::string line = templine;
-
+
#ifndef _WIN32
// Check for CRLF eol and convert it to LF
if (!line.empty() && line.at(line.size()-1) == '\r')
@@ -405,12 +363,25 @@ bool IniFile::Load(const char* filename)
{
// New section!
std::string sub = line.substr(1, endpos - 1);
- sections.push_back(Section(sub));
+ current_section = GetOrCreateSection(sub.c_str());
}
}
else
{
- sections[sections.size() - 1].lines.push_back(line);
+ if (current_section)
+ {
+ std::string key, value;
+ ParseLine(line, &key, &value);
+
+ // Lines starting with '$' or '+' are kept verbatim. Kind
+ // of a hack, but the support for raw lines inside an INI
+ // is a hack anyway.
+ if ((key == "" && value == "")
+ || (line.size() >= 1 && (line[0] == '$' || line[0] == '+')))
+ current_section->lines.push_back(line.c_str());
+ else
+ current_section->Set(key, value.c_str());
+ }
}
}
}
@@ -429,27 +400,33 @@ bool IniFile::Save(const char* filename)
return false;
}
- // Currently testing if dolphin community can handle the requirements of C++11 compilation
- // If you get a compiler error on this line, your compiler is probably old.
- // Update to g++ 4.4 or a recent version of clang (XCode 4.2 on OS X).
- // If you don't want to update, complain in a google code issue, the dolphin forums or #dolphin-emu.
for (auto iter = sections.begin(); iter != sections.end(); ++iter)
{
const Section& section = *iter;
- if (section.name != "")
- {
+ if (section.keys_order.size() != 0 || section.lines.size() != 0)
out << "[" << section.name << "]" << std::endl;
- }
- for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
+ if (section.keys_order.size() == 0)
+ {
+ for (auto liter = section.lines.begin(); liter != section.lines.end(); ++liter)
+ {
+ std::string s = *liter;
+ out << s << std::endl;
+ }
+ }
+ else
{
- std::string s = *liter;
- out << s << std::endl;
+ for (auto kvit = section.keys_order.begin(); kvit != section.keys_order.end(); ++kvit)
+ {
+ auto pair = section.values.find(*kvit);
+ out << pair->first << " = " << pair->second << std::endl;
+ }
}
}
out.close();
+
return true;
}