[Scummvm-cvs-logs] scummvm master -> de952ae0b9226a67c8d20916e29f81258a2f6223
lordhoto
lordhoto at gmail.com
Fri Aug 9 00:57:25 CEST 2013
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
63750d6780 COMMON: Rename ConfigFile to INIFile.
6da6e4e686 COMMON: Remove outdated comments on INIFile.
0dae60a357 COMMON: Remove commented out include in config-manager.h.
de952ae0b9 Merge pull request #373 from lordhoto/ini-file
Commit: 63750d678068aa92ee95dc9de2b2908a983b489d
https://github.com/scummvm/scummvm/commit/63750d678068aa92ee95dc9de2b2908a983b489d
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-08-08T07:28:38-07:00
Commit Message:
COMMON: Rename ConfigFile to INIFile.
This clears up that 'ConfigFile' is actually a class handling only INI-files.
Changed paths:
A common/ini-file.cpp
A common/ini-file.h
R common/config-file.cpp
R common/config-file.h
common/config-manager.h
common/module.mk
engines/composer/composer.h
engines/gob/iniconfig.cpp
engines/gob/iniconfig.h
engines/mohawk/livingbooks.cpp
engines/mohawk/livingbooks.h
engines/mohawk/livingbooks_lbx.cpp
engines/scumm/he/script_v80he.cpp
engines/testbed/config.cpp
engines/testbed/config.h
diff --git a/common/config-file.cpp b/common/config-file.cpp
deleted file mode 100644
index 0ce6dcf..0000000
--- a/common/config-file.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/config-file.h"
-#include "common/file.h"
-#include "common/savefile.h"
-#include "common/system.h"
-#include "common/textconsole.h"
-
-namespace Common {
-
-bool ConfigFile::isValidName(const String &name) {
- const char *p = name.c_str();
- while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.'))
- p++;
- return *p == 0;
-}
-
-ConfigFile::ConfigFile() {
-}
-
-ConfigFile::~ConfigFile() {
-}
-
-void ConfigFile::clear() {
- _sections.clear();
-}
-
-bool ConfigFile::loadFromFile(const String &filename) {
- File file;
- if (file.open(filename))
- return loadFromStream(file);
- else
- return false;
-}
-
-bool ConfigFile::loadFromSaveFile(const char *filename) {
- assert(g_system);
- SaveFileManager *saveFileMan = g_system->getSavefileManager();
- SeekableReadStream *loadFile;
-
- assert(saveFileMan);
- if (!(loadFile = saveFileMan->openForLoading(filename)))
- return false;
-
- bool status = loadFromStream(*loadFile);
- delete loadFile;
- return status;
-}
-
-bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
- Section section;
- KeyValue kv;
- String comment;
- int lineno = 0;
-
- // TODO: Detect if a section occurs multiple times (or likewise, if
- // a key occurs multiple times inside one section).
-
- while (!stream.eos() && !stream.err()) {
- lineno++;
-
- // Read a line
- String line = stream.readLine();
-
- if (line.size() == 0) {
- // Do nothing
- } else if (line[0] == '#' || line[0] == ';' || line.hasPrefix("//")) {
- // Accumulate comments here. Once we encounter either the start
- // of a new section, or a key-value-pair, we associate the value
- // of the 'comment' variable with that entity. The semicolon and
- // C++-style comments are used for Living Books games in Mohawk.
- comment += line;
- comment += "\n";
- } else if (line[0] == '(') {
- // HACK: The following is a hack added by Kirben to support the
- // "map.ini" used in the HE SCUMM game "SPY Fox in Hold the Mustard".
- //
- // It would be nice if this hack could be restricted to that game,
- // but the current design of this class doesn't allow to do that
- // in a nice fashion (a "isMustard" parameter is *not* a nice
- // solution).
- comment += line;
- comment += "\n";
- } else if (line[0] == '[') {
- // It's a new section which begins here.
- const char *p = line.c_str() + 1;
- // Get the section name, and check whether it's valid (that
- // is, verify that it only consists of alphanumerics,
- // periods, dashes and underscores). Mohawk Living Books games
- // can have periods in their section names.
- while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.'))
- p++;
-
- if (*p == '\0')
- error("ConfigFile::loadFromStream: missing ] in line %d", lineno);
- else if (*p != ']')
- error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno);
-
- // Previous section is finished now, store it.
- if (!section.name.empty())
- _sections.push_back(section);
-
- section.name = String(line.c_str() + 1, p);
- section.keys.clear();
- section.comment = comment;
- comment.clear();
-
- assert(isValidName(section.name));
- } else {
- // This line should be a line with a 'key=value' pair, or an empty one.
-
- // Skip leading whitespaces
- const char *t = line.c_str();
- while (isSpace(*t))
- t++;
-
- // Skip empty lines / lines with only whitespace
- if (*t == 0)
- continue;
-
- // If no section has been set, this config file is invalid!
- if (section.name.empty()) {
- error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
- }
-
- // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
- const char *p = strchr(t, '=');
- if (!p)
- error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
-
- // Extract the key/value pair
- kv.key = String(t, p);
- kv.value = String(p + 1);
-
- // Trim of spaces
- kv.key.trim();
- kv.value.trim();
-
- // Store comment
- kv.comment = comment;
- comment.clear();
-
- assert(isValidName(kv.key));
-
- section.keys.push_back(kv);
- }
- }
-
- // Save last section
- if (!section.name.empty())
- _sections.push_back(section);
-
- return (!stream.err() || stream.eos());
-}
-
-bool ConfigFile::saveToFile(const String &filename) {
- DumpFile file;
- if (file.open(filename))
- return saveToStream(file);
- else
- return false;
-}
-
-bool ConfigFile::saveToSaveFile(const char *filename) {
- assert(g_system);
- SaveFileManager *saveFileMan = g_system->getSavefileManager();
- WriteStream *saveFile;
-
- assert(saveFileMan);
- if (!(saveFile = saveFileMan->openForSaving(filename)))
- return false;
-
- bool status = saveToStream(*saveFile);
- delete saveFile;
- return status;
-}
-
-bool ConfigFile::saveToStream(WriteStream &stream) {
- for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
- // Write out the section comment, if any
- if (! i->comment.empty()) {
- stream.writeString(i->comment);
- }
-
- // Write out the section name
- stream.writeByte('[');
- stream.writeString(i->name);
- stream.writeByte(']');
- stream.writeByte('\n');
-
- // Write out the key/value pairs
- for (List<KeyValue>::iterator kv = i->keys.begin(); kv != i->keys.end(); ++kv) {
- // Write out the comment, if any
- if (! kv->comment.empty()) {
- stream.writeString(kv->comment);
- }
- // Write out the key/value pair
- stream.writeString(kv->key);
- stream.writeByte('=');
- stream.writeString(kv->value);
- stream.writeByte('\n');
- }
- }
-
- stream.flush();
- return !stream.err();
-}
-
-void ConfigFile::addSection(const String §ion) {
- Section *s = getSection(section);
- if (s)
- return;
-
- Section newSection;
- newSection.name = section;
- _sections.push_back(newSection);
-}
-
-void ConfigFile::removeSection(const String §ion) {
- assert(isValidName(section));
- for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (section.equalsIgnoreCase(i->name)) {
- _sections.erase(i);
- return;
- }
- }
-}
-
-bool ConfigFile::hasSection(const String §ion) const {
- assert(isValidName(section));
- const Section *s = getSection(section);
- return s != 0;
-}
-
-void ConfigFile::renameSection(const String &oldName, const String &newName) {
- assert(isValidName(oldName));
- assert(isValidName(newName));
-
- Section *os = getSection(oldName);
- const Section *ns = getSection(newName);
- if (os) {
- // HACK: For now we just print a warning, for more info see the TODO
- // below.
- if (ns)
- warning("ConfigFile::renameSection: Section name \"%s\" already used", newName.c_str());
- else
- os->name = newName;
- }
- // TODO: Check here whether there already is a section with the
- // new name. Not sure how to cope with that case, we could:
- // - simply remove the existing "newName" section
- // - error out
- // - merge the two sections "oldName" and "newName"
-}
-
-
-bool ConfigFile::hasKey(const String &key, const String §ion) const {
- assert(isValidName(key));
- assert(isValidName(section));
-
- const Section *s = getSection(section);
- if (!s)
- return false;
- return s->hasKey(key);
-}
-
-void ConfigFile::removeKey(const String &key, const String §ion) {
- assert(isValidName(key));
- assert(isValidName(section));
-
- Section *s = getSection(section);
- if (s)
- s->removeKey(key);
-}
-
-bool ConfigFile::getKey(const String &key, const String §ion, String &value) const {
- assert(isValidName(key));
- assert(isValidName(section));
-
- const Section *s = getSection(section);
- if (!s)
- return false;
- const KeyValue *kv = s->getKey(key);
- if (!kv)
- return false;
- value = kv->value;
- return true;
-}
-
-void ConfigFile::setKey(const String &key, const String §ion, const String &value) {
- assert(isValidName(key));
- assert(isValidName(section));
- // TODO: Verify that value is valid, too. In particular, it shouldn't
- // contain CR or LF...
-
- Section *s = getSection(section);
- if (!s) {
- KeyValue newKV;
- newKV.key = key;
- newKV.value = value;
-
- Section newSection;
- newSection.name = section;
- newSection.keys.push_back(newKV);
-
- _sections.push_back(newSection);
- } else {
- s->setKey(key, value);
- }
-}
-
-const ConfigFile::SectionKeyList ConfigFile::getKeys(const String §ion) const {
- const Section *s = getSection(section);
-
- return s->getKeys();
-}
-
-ConfigFile::Section *ConfigFile::getSection(const String §ion) {
- for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (section.equalsIgnoreCase(i->name)) {
- return &(*i);
- }
- }
- return 0;
-}
-
-const ConfigFile::Section *ConfigFile::getSection(const String §ion) const {
- for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) {
- if (section.equalsIgnoreCase(i->name)) {
- return &(*i);
- }
- }
- return 0;
-}
-
-bool ConfigFile::Section::hasKey(const String &key) const {
- return getKey(key) != 0;
-}
-
-const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const {
- for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
- if (key.equalsIgnoreCase(i->key)) {
- return &(*i);
- }
- }
- return 0;
-}
-
-void ConfigFile::Section::setKey(const String &key, const String &value) {
- for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
- if (key.equalsIgnoreCase(i->key)) {
- i->value = value;
- return;
- }
- }
-
- KeyValue newKV;
- newKV.key = key;
- newKV.value = value;
- keys.push_back(newKV);
-}
-
-void ConfigFile::Section::removeKey(const String &key) {
- for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
- if (key.equalsIgnoreCase(i->key)) {
- keys.erase(i);
- return;
- }
- }
-}
-
-} // End of namespace Common
diff --git a/common/config-file.h b/common/config-file.h
deleted file mode 100644
index 8bba851..0000000
--- a/common/config-file.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef COMMON_CONFIG_FILE_H
-#define COMMON_CONFIG_FILE_H
-
-#include "common/hash-str.h"
-#include "common/list.h"
-#include "common/str.h"
-
-namespace Common {
-
-class SeekableReadStream;
-class WriteStream;
-
-/**
- * This class allows reading/writing INI style config files.
- * It is used by the ConfigManager for storage, but can also
- * be used by other code if it needs to read/write custom INI
- * files.
- *
- * Lines starting with a '#' are ignored (i.e. treated as comments).
- * Some effort is made to preserve comments, though.
- *
- * This class makes no attempts to provide fast access to key/value pairs.
- * In particular, it stores all sections and k/v pairs in lists, not
- * in dictionaries/maps. This makes it very easy to read/write the data
- * from/to files, but of course is not appropriate for fast access.
- * The main reason is that this class is indeed geared toward doing precisely
- * that!
- * If you need fast access to the game config, use higher level APIs, like the
- * one provided by ConfigManager.
- */
-class ConfigFile {
-public:
- struct KeyValue {
- String key;
- String value;
- String comment;
- };
-
- typedef List<KeyValue> SectionKeyList;
-
- /** A section in a config file. I.e. corresponds to something like this:
- * [mySection]
- * key=value
- *
- * Comments are also stored, to keep users happy who like editing their
- * config files manually.
- */
- struct Section {
- String name;
- List<KeyValue> keys;
- String comment;
-
- bool hasKey(const String &key) const;
- const KeyValue* getKey(const String &key) const;
- void setKey(const String &key, const String &value);
- void removeKey(const String &key);
- const SectionKeyList getKeys() const { return keys; }
- };
-
- typedef List<Section> SectionList;
-
-public:
- ConfigFile();
- ~ConfigFile();
-
- // TODO: Maybe add a copy constructor etc.?
-
- /**
- * Check whether the given string is a valid section or key name.
- * For that, it must only consist of letters, numbers, dashes and
- * underscores. In particular, white space and "#", "=", "[", "]"
- * are not valid!
- */
- static bool isValidName(const String &name);
-
- /** Reset everything stored in this config file. */
- void clear();
-
- bool loadFromFile(const String &filename);
- bool loadFromSaveFile(const char *filename);
- bool loadFromStream(SeekableReadStream &stream);
- bool saveToFile(const String &filename);
- bool saveToSaveFile(const char *filename);
- bool saveToStream(WriteStream &stream);
-
- bool hasSection(const String §ion) const;
- void addSection(const String §ion);
- void removeSection(const String §ion);
- void renameSection(const String &oldName, const String &newName);
-
- bool hasKey(const String &key, const String §ion) const;
- bool getKey(const String &key, const String §ion, String &value) const;
- void setKey(const String &key, const String §ion, const String &value);
- void removeKey(const String &key, const String §ion);
-
- const SectionList getSections() const { return _sections; }
- const SectionKeyList getKeys(const String §ion) const;
-
- void listKeyValues(StringMap &kv);
-
-private:
- SectionList _sections;
-
- Section *getSection(const String §ion);
- const Section *getSection(const String §ion) const;
-};
-
-/*
-- ConfigMan owns a config file
-- allow direct access to that config file (for the launcher)
-- simplify and unify the regular ConfigMan API in exchange
-
-
-*/
-
-} // End of namespace Common
-
-#endif
diff --git a/common/config-manager.h b/common/config-manager.h
index d43a7be..45a1f2d 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -24,7 +24,7 @@
#define COMMON_CONFIG_MANAGER_H
#include "common/array.h"
-//#include "common/config-file.h"
+//#include "common/ini-file.h"
#include "common/hashmap.h"
#include "common/singleton.h"
#include "common/str.h"
diff --git a/common/ini-file.cpp b/common/ini-file.cpp
new file mode 100644
index 0000000..be5247d
--- /dev/null
+++ b/common/ini-file.cpp
@@ -0,0 +1,392 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/ini-file.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+
+namespace Common {
+
+bool INIFile::isValidName(const String &name) {
+ const char *p = name.c_str();
+ while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.'))
+ p++;
+ return *p == 0;
+}
+
+INIFile::INIFile() {
+}
+
+INIFile::~INIFile() {
+}
+
+void INIFile::clear() {
+ _sections.clear();
+}
+
+bool INIFile::loadFromFile(const String &filename) {
+ File file;
+ if (file.open(filename))
+ return loadFromStream(file);
+ else
+ return false;
+}
+
+bool INIFile::loadFromSaveFile(const char *filename) {
+ assert(g_system);
+ SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ SeekableReadStream *loadFile;
+
+ assert(saveFileMan);
+ if (!(loadFile = saveFileMan->openForLoading(filename)))
+ return false;
+
+ bool status = loadFromStream(*loadFile);
+ delete loadFile;
+ return status;
+}
+
+bool INIFile::loadFromStream(SeekableReadStream &stream) {
+ Section section;
+ KeyValue kv;
+ String comment;
+ int lineno = 0;
+
+ // TODO: Detect if a section occurs multiple times (or likewise, if
+ // a key occurs multiple times inside one section).
+
+ while (!stream.eos() && !stream.err()) {
+ lineno++;
+
+ // Read a line
+ String line = stream.readLine();
+
+ if (line.size() == 0) {
+ // Do nothing
+ } else if (line[0] == '#' || line[0] == ';' || line.hasPrefix("//")) {
+ // Accumulate comments here. Once we encounter either the start
+ // of a new section, or a key-value-pair, we associate the value
+ // of the 'comment' variable with that entity. The semicolon and
+ // C++-style comments are used for Living Books games in Mohawk.
+ comment += line;
+ comment += "\n";
+ } else if (line[0] == '(') {
+ // HACK: The following is a hack added by Kirben to support the
+ // "map.ini" used in the HE SCUMM game "SPY Fox in Hold the Mustard".
+ //
+ // It would be nice if this hack could be restricted to that game,
+ // but the current design of this class doesn't allow to do that
+ // in a nice fashion (a "isMustard" parameter is *not* a nice
+ // solution).
+ comment += line;
+ comment += "\n";
+ } else if (line[0] == '[') {
+ // It's a new section which begins here.
+ const char *p = line.c_str() + 1;
+ // Get the section name, and check whether it's valid (that
+ // is, verify that it only consists of alphanumerics,
+ // periods, dashes and underscores). Mohawk Living Books games
+ // can have periods in their section names.
+ while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.'))
+ p++;
+
+ if (*p == '\0')
+ error("INIFile::loadFromStream: missing ] in line %d", lineno);
+ else if (*p != ']')
+ error("INIFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno);
+
+ // Previous section is finished now, store it.
+ if (!section.name.empty())
+ _sections.push_back(section);
+
+ section.name = String(line.c_str() + 1, p);
+ section.keys.clear();
+ section.comment = comment;
+ comment.clear();
+
+ assert(isValidName(section.name));
+ } else {
+ // This line should be a line with a 'key=value' pair, or an empty one.
+
+ // Skip leading whitespaces
+ const char *t = line.c_str();
+ while (isSpace(*t))
+ t++;
+
+ // Skip empty lines / lines with only whitespace
+ if (*t == 0)
+ continue;
+
+ // If no section has been set, this config file is invalid!
+ if (section.name.empty()) {
+ error("INIFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
+ }
+
+ // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
+ const char *p = strchr(t, '=');
+ if (!p)
+ error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
+
+ // Extract the key/value pair
+ kv.key = String(t, p);
+ kv.value = String(p + 1);
+
+ // Trim of spaces
+ kv.key.trim();
+ kv.value.trim();
+
+ // Store comment
+ kv.comment = comment;
+ comment.clear();
+
+ assert(isValidName(kv.key));
+
+ section.keys.push_back(kv);
+ }
+ }
+
+ // Save last section
+ if (!section.name.empty())
+ _sections.push_back(section);
+
+ return (!stream.err() || stream.eos());
+}
+
+bool INIFile::saveToFile(const String &filename) {
+ DumpFile file;
+ if (file.open(filename))
+ return saveToStream(file);
+ else
+ return false;
+}
+
+bool INIFile::saveToSaveFile(const char *filename) {
+ assert(g_system);
+ SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ WriteStream *saveFile;
+
+ assert(saveFileMan);
+ if (!(saveFile = saveFileMan->openForSaving(filename)))
+ return false;
+
+ bool status = saveToStream(*saveFile);
+ delete saveFile;
+ return status;
+}
+
+bool INIFile::saveToStream(WriteStream &stream) {
+ for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
+ // Write out the section comment, if any
+ if (! i->comment.empty()) {
+ stream.writeString(i->comment);
+ }
+
+ // Write out the section name
+ stream.writeByte('[');
+ stream.writeString(i->name);
+ stream.writeByte(']');
+ stream.writeByte('\n');
+
+ // Write out the key/value pairs
+ for (List<KeyValue>::iterator kv = i->keys.begin(); kv != i->keys.end(); ++kv) {
+ // Write out the comment, if any
+ if (! kv->comment.empty()) {
+ stream.writeString(kv->comment);
+ }
+ // Write out the key/value pair
+ stream.writeString(kv->key);
+ stream.writeByte('=');
+ stream.writeString(kv->value);
+ stream.writeByte('\n');
+ }
+ }
+
+ stream.flush();
+ return !stream.err();
+}
+
+void INIFile::addSection(const String §ion) {
+ Section *s = getSection(section);
+ if (s)
+ return;
+
+ Section newSection;
+ newSection.name = section;
+ _sections.push_back(newSection);
+}
+
+void INIFile::removeSection(const String §ion) {
+ assert(isValidName(section));
+ for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
+ if (section.equalsIgnoreCase(i->name)) {
+ _sections.erase(i);
+ return;
+ }
+ }
+}
+
+bool INIFile::hasSection(const String §ion) const {
+ assert(isValidName(section));
+ const Section *s = getSection(section);
+ return s != 0;
+}
+
+void INIFile::renameSection(const String &oldName, const String &newName) {
+ assert(isValidName(oldName));
+ assert(isValidName(newName));
+
+ Section *os = getSection(oldName);
+ const Section *ns = getSection(newName);
+ if (os) {
+ // HACK: For now we just print a warning, for more info see the TODO
+ // below.
+ if (ns)
+ warning("INIFile::renameSection: Section name \"%s\" already used", newName.c_str());
+ else
+ os->name = newName;
+ }
+ // TODO: Check here whether there already is a section with the
+ // new name. Not sure how to cope with that case, we could:
+ // - simply remove the existing "newName" section
+ // - error out
+ // - merge the two sections "oldName" and "newName"
+}
+
+
+bool INIFile::hasKey(const String &key, const String §ion) const {
+ assert(isValidName(key));
+ assert(isValidName(section));
+
+ const Section *s = getSection(section);
+ if (!s)
+ return false;
+ return s->hasKey(key);
+}
+
+void INIFile::removeKey(const String &key, const String §ion) {
+ assert(isValidName(key));
+ assert(isValidName(section));
+
+ Section *s = getSection(section);
+ if (s)
+ s->removeKey(key);
+}
+
+bool INIFile::getKey(const String &key, const String §ion, String &value) const {
+ assert(isValidName(key));
+ assert(isValidName(section));
+
+ const Section *s = getSection(section);
+ if (!s)
+ return false;
+ const KeyValue *kv = s->getKey(key);
+ if (!kv)
+ return false;
+ value = kv->value;
+ return true;
+}
+
+void INIFile::setKey(const String &key, const String §ion, const String &value) {
+ assert(isValidName(key));
+ assert(isValidName(section));
+ // TODO: Verify that value is valid, too. In particular, it shouldn't
+ // contain CR or LF...
+
+ Section *s = getSection(section);
+ if (!s) {
+ KeyValue newKV;
+ newKV.key = key;
+ newKV.value = value;
+
+ Section newSection;
+ newSection.name = section;
+ newSection.keys.push_back(newKV);
+
+ _sections.push_back(newSection);
+ } else {
+ s->setKey(key, value);
+ }
+}
+
+const INIFile::SectionKeyList INIFile::getKeys(const String §ion) const {
+ const Section *s = getSection(section);
+
+ return s->getKeys();
+}
+
+INIFile::Section *INIFile::getSection(const String §ion) {
+ for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
+ if (section.equalsIgnoreCase(i->name)) {
+ return &(*i);
+ }
+ }
+ return 0;
+}
+
+const INIFile::Section *INIFile::getSection(const String §ion) const {
+ for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) {
+ if (section.equalsIgnoreCase(i->name)) {
+ return &(*i);
+ }
+ }
+ return 0;
+}
+
+bool INIFile::Section::hasKey(const String &key) const {
+ return getKey(key) != 0;
+}
+
+const INIFile::KeyValue* INIFile::Section::getKey(const String &key) const {
+ for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
+ if (key.equalsIgnoreCase(i->key)) {
+ return &(*i);
+ }
+ }
+ return 0;
+}
+
+void INIFile::Section::setKey(const String &key, const String &value) {
+ for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
+ if (key.equalsIgnoreCase(i->key)) {
+ i->value = value;
+ return;
+ }
+ }
+
+ KeyValue newKV;
+ newKV.key = key;
+ newKV.value = value;
+ keys.push_back(newKV);
+}
+
+void INIFile::Section::removeKey(const String &key) {
+ for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) {
+ if (key.equalsIgnoreCase(i->key)) {
+ keys.erase(i);
+ return;
+ }
+ }
+}
+
+} // End of namespace Common
diff --git a/common/ini-file.h b/common/ini-file.h
new file mode 100644
index 0000000..c7da6de
--- /dev/null
+++ b/common/ini-file.h
@@ -0,0 +1,140 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMMON_INI_FILE_H
+#define COMMON_INI_FILE_H
+
+#include "common/hash-str.h"
+#include "common/list.h"
+#include "common/str.h"
+
+namespace Common {
+
+class SeekableReadStream;
+class WriteStream;
+
+/**
+ * This class allows reading/writing INI style config files.
+ * It is used by the ConfigManager for storage, but can also
+ * be used by other code if it needs to read/write custom INI
+ * files.
+ *
+ * Lines starting with a '#' are ignored (i.e. treated as comments).
+ * Some effort is made to preserve comments, though.
+ *
+ * This class makes no attempts to provide fast access to key/value pairs.
+ * In particular, it stores all sections and k/v pairs in lists, not
+ * in dictionaries/maps. This makes it very easy to read/write the data
+ * from/to files, but of course is not appropriate for fast access.
+ * The main reason is that this class is indeed geared toward doing precisely
+ * that!
+ * If you need fast access to the game config, use higher level APIs, like the
+ * one provided by ConfigManager.
+ */
+class INIFile {
+public:
+ struct KeyValue {
+ String key;
+ String value;
+ String comment;
+ };
+
+ typedef List<KeyValue> SectionKeyList;
+
+ /** A section in a ini file. I.e. corresponds to something like this:
+ * [mySection]
+ * key=value
+ *
+ * Comments are also stored, to keep users happy who like editing their
+ * ini files manually.
+ */
+ struct Section {
+ String name;
+ List<KeyValue> keys;
+ String comment;
+
+ bool hasKey(const String &key) const;
+ const KeyValue* getKey(const String &key) const;
+ void setKey(const String &key, const String &value);
+ void removeKey(const String &key);
+ const SectionKeyList getKeys() const { return keys; }
+ };
+
+ typedef List<Section> SectionList;
+
+public:
+ INIFile();
+ ~INIFile();
+
+ // TODO: Maybe add a copy constructor etc.?
+
+ /**
+ * Check whether the given string is a valid section or key name.
+ * For that, it must only consist of letters, numbers, dashes and
+ * underscores. In particular, white space and "#", "=", "[", "]"
+ * are not valid!
+ */
+ static bool isValidName(const String &name);
+
+ /** Reset everything stored in this ini file. */
+ void clear();
+
+ bool loadFromFile(const String &filename);
+ bool loadFromSaveFile(const char *filename);
+ bool loadFromStream(SeekableReadStream &stream);
+ bool saveToFile(const String &filename);
+ bool saveToSaveFile(const char *filename);
+ bool saveToStream(WriteStream &stream);
+
+ bool hasSection(const String §ion) const;
+ void addSection(const String §ion);
+ void removeSection(const String §ion);
+ void renameSection(const String &oldName, const String &newName);
+
+ bool hasKey(const String &key, const String §ion) const;
+ bool getKey(const String &key, const String §ion, String &value) const;
+ void setKey(const String &key, const String §ion, const String &value);
+ void removeKey(const String &key, const String §ion);
+
+ const SectionList getSections() const { return _sections; }
+ const SectionKeyList getKeys(const String §ion) const;
+
+ void listKeyValues(StringMap &kv);
+
+private:
+ SectionList _sections;
+
+ Section *getSection(const String §ion);
+ const Section *getSection(const String §ion) const;
+};
+
+/*
+- ConfigMan owns a config file
+- allow direct access to that config file (for the launcher)
+- simplify and unify the regular ConfigMan API in exchange
+
+
+*/
+
+} // End of namespace Common
+
+#endif
diff --git a/common/module.mk b/common/module.mk
index 9f9126c..1b34d15 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -2,7 +2,6 @@ MODULE := common
MODULE_OBJS := \
archive.o \
- config-file.o \
config-manager.o \
coroutines.o \
dcl.o \
@@ -15,6 +14,7 @@ MODULE_OBJS := \
gui_options.o \
hashmap.o \
iff_container.o \
+ ini-file.o \
installshield_cab.o \
language.o \
localization.o \
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
index 33a5356..7d80224 100644
--- a/engines/composer/composer.h
+++ b/engines/composer/composer.h
@@ -23,7 +23,7 @@
#ifndef COMPOSER_H
#define COMPOSER_H
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/random.h"
#include "common/system.h"
#include "common/debug.h"
@@ -174,7 +174,7 @@ private:
Common::List<Sprite> _sprites;
uint _directoriesToStrip;
- Common::ConfigFile _bookIni;
+ Common::INIFile _bookIni;
Common::String _bookGroup;
Common::List<Library> _libraries;
Common::Array<PendingPageChange> _pendingPageChanges;
diff --git a/engines/gob/iniconfig.cpp b/engines/gob/iniconfig.cpp
index bba5317..032231b 100644
--- a/engines/gob/iniconfig.cpp
+++ b/engines/gob/iniconfig.cpp
@@ -73,7 +73,7 @@ bool INIConfig::getConfig(const Common::String &file, Config &config) {
}
bool INIConfig::openConfig(const Common::String &file, Config &config) {
- config.config = new Common::ConfigFile();
+ config.config = new Common::INIFile();
config.created = false;
if (!config.config->loadFromFile(file)) {
@@ -89,7 +89,7 @@ bool INIConfig::openConfig(const Common::String &file, Config &config) {
}
bool INIConfig::createConfig(const Common::String &file, Config &config) {
- config.config = new Common::ConfigFile();
+ config.config = new Common::INIFile();
config.created = true;
_configs.setVal(file, config);
diff --git a/engines/gob/iniconfig.h b/engines/gob/iniconfig.h
index bf60f2d..c189017 100644
--- a/engines/gob/iniconfig.h
+++ b/engines/gob/iniconfig.h
@@ -24,7 +24,7 @@
#define GOB_INICONFIG_H
#include "common/str.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/hashmap.h"
namespace Gob {
@@ -43,7 +43,7 @@ public:
private:
struct Config {
- Common::ConfigFile *config;
+ Common::INIFile *config;
bool created;
};
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index efa0dd3..634ff44 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -311,8 +311,8 @@ void MohawkEngine_LivingBooks::loadBookInfo(const Common::String &filename) {
// - fDebugWindow (always 0?)
if (_bookInfoFile.hasSection("Globals")) {
- const Common::ConfigFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals");
- for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
+ const Common::INIFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals");
+ for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str());
LBCode tempCode(this, 0);
uint offset = tempCode.parseCode(command);
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 76da7d8..615fcd0 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -28,7 +28,7 @@
#include "mohawk/livingbooks_graphics.h"
#include "mohawk/sound.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/rect.h"
#include "common/queue.h"
#include "common/random.h"
@@ -759,7 +759,7 @@ public:
private:
LivingBooksConsole *_console;
- Common::ConfigFile _bookInfoFile;
+ Common::INIFile _bookInfoFile;
Common::String getBookInfoFileName() const;
void loadBookInfo(const Common::String &filename);
diff --git a/engines/mohawk/livingbooks_lbx.cpp b/engines/mohawk/livingbooks_lbx.cpp
index 2b8b22e..dcf8caa 100644
--- a/engines/mohawk/livingbooks_lbx.cpp
+++ b/engines/mohawk/livingbooks_lbx.cpp
@@ -33,7 +33,7 @@ public:
bool call(uint callId, const Common::Array<LBValue> ¶ms, LBValue &result);
protected:
- Common::ConfigFile _dataFile;
+ Common::INIFile _dataFile;
Common::String _curSection;
void open(const Common::String &filename);
@@ -77,8 +77,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu
case kLBXDataFileGetSectionList:
{
Common::SharedPtr<LBList> list = Common::SharedPtr<LBList>(new LBList);
- Common::ConfigFile::SectionList sections = _dataFile.getSections();
- for (Common::List<Common::ConfigFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i)
+ Common::INIFile::SectionList sections = _dataFile.getSections();
+ for (Common::List<Common::INIFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i)
list->array.push_back(LBValue(i->name));
result = LBValue(list);
}
@@ -103,8 +103,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu
error("incorrect number of parameters (%d) to LBXDataFile::loadCurSectionVars", params.size());
{
- const Common::ConfigFile::SectionKeyList globals = _dataFile.getKeys(_curSection);
- for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
+ const Common::INIFile::SectionKeyList globals = _dataFile.getKeys(_curSection);
+ for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) {
Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str());
LBCode tempCode(_vm, 0);
uint offset = tempCode.parseCode(command);
diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp
index eb62b65..ae43d71 100644
--- a/engines/scumm/he/script_v80he.cpp
+++ b/engines/scumm/he/script_v80he.cpp
@@ -23,7 +23,7 @@
#ifdef ENABLE_HE
#include "common/archive.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/config-manager.h"
#include "common/macresman.h"
#include "common/savefile.h"
@@ -180,7 +180,7 @@ void ScummEngine_v80he::o80_readConfigFile() {
}
} else {
// Normal Windows INI files
- Common::ConfigFile confFile;
+ Common::INIFile confFile;
if (!strcmp((char *)filename + r, "map.ini"))
confFile.loadFromFile((const char *)filename + r);
else
@@ -250,7 +250,7 @@ void ScummEngine_v80he::o80_writeConfigFile() {
memcpy(section, "BluesTreasureHunt-Disc2\0", 24);
}
- Common::ConfigFile ConfFile;
+ Common::INIFile ConfFile;
ConfFile.loadFromSaveFile((const char *)filename + r);
ConfFile.setKey((char *)option, (char *)section, (char *)string);
ConfFile.saveToSaveFile((const char *)filename + r);
diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp
index 6b56616..a40d239 100644
--- a/engines/testbed/config.cpp
+++ b/engines/testbed/config.cpp
@@ -213,22 +213,22 @@ void TestbedConfigManager::parseConfigFile() {
return;
}
_configFileInterface.loadFromStream(*rs);
- Common::ConfigFile::SectionList sections = _configFileInterface.getSections();
+ Common::INIFile::SectionList sections = _configFileInterface.getSections();
Testsuite *currTS = 0;
- for (Common::ConfigFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) {
+ for (Common::INIFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) {
if (i->name.equalsIgnoreCase("Global")) {
// Global params may be directly queried, ignore them
} else {
// A testsuite, process it.
currTS = getTestsuiteByName(i->name);
- Common::ConfigFile::SectionKeyList kList = i->getKeys();
+ Common::INIFile::SectionKeyList kList = i->getKeys();
if (!currTS) {
Testsuite::logPrintf("Warning! Error in config: Testsuite %s not found\n", i->name.c_str());
continue;
}
- for (Common::ConfigFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) {
+ for (Common::INIFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) {
if (j->key.equalsIgnoreCase("this")) {
currTS->enable(stringToBool(j->value));
} else {
diff --git a/engines/testbed/config.h b/engines/testbed/config.h
index fd5588a..d611ae4 100644
--- a/engines/testbed/config.h
+++ b/engines/testbed/config.h
@@ -24,7 +24,7 @@
#include "common/array.h"
-#include "common/config-file.h"
+#include "common/ini-file.h"
#include "common/str-array.h"
#include "common/tokenizer.h"
@@ -62,7 +62,7 @@ public:
private:
Common::Array<Testsuite *> &_testsuiteList;
Common::String _configFileName;
- Common::ConfigFile _configFileInterface;
+ Common::INIFile _configFileInterface;
void parseConfigFile();
};
Commit: 6da6e4e68628bba656c3c3e1d2f6f9e27013f8f8
https://github.com/scummvm/scummvm/commit/6da6e4e68628bba656c3c3e1d2f6f9e27013f8f8
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-08-08T07:30:38-07:00
Commit Message:
COMMON: Remove outdated comments on INIFile.
These very old comments claimed that ConfigManager uses INIFile. This is not
true however. Thus removing them should clear things up a little bit.
Changed paths:
common/ini-file.h
diff --git a/common/ini-file.h b/common/ini-file.h
index c7da6de..1d94ce7 100644
--- a/common/ini-file.h
+++ b/common/ini-file.h
@@ -34,9 +34,6 @@ class WriteStream;
/**
* This class allows reading/writing INI style config files.
- * It is used by the ConfigManager for storage, but can also
- * be used by other code if it needs to read/write custom INI
- * files.
*
* Lines starting with a '#' are ignored (i.e. treated as comments).
* Some effort is made to preserve comments, though.
@@ -47,8 +44,6 @@ class WriteStream;
* from/to files, but of course is not appropriate for fast access.
* The main reason is that this class is indeed geared toward doing precisely
* that!
- * If you need fast access to the game config, use higher level APIs, like the
- * one provided by ConfigManager.
*/
class INIFile {
public:
@@ -127,14 +122,6 @@ private:
const Section *getSection(const String §ion) const;
};
-/*
-- ConfigMan owns a config file
-- allow direct access to that config file (for the launcher)
-- simplify and unify the regular ConfigMan API in exchange
-
-
-*/
-
} // End of namespace Common
#endif
Commit: 0dae60a3577a78f75ae3cf2d2dc88177ba6f128e
https://github.com/scummvm/scummvm/commit/0dae60a3577a78f75ae3cf2d2dc88177ba6f128e
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2013-08-08T07:32:41-07:00
Commit Message:
COMMON: Remove commented out include in config-manager.h.
Changed paths:
common/config-manager.h
diff --git a/common/config-manager.h b/common/config-manager.h
index 45a1f2d..6295a93 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -24,7 +24,6 @@
#define COMMON_CONFIG_MANAGER_H
#include "common/array.h"
-//#include "common/ini-file.h"
#include "common/hashmap.h"
#include "common/singleton.h"
#include "common/str.h"
Commit: de952ae0b9226a67c8d20916e29f81258a2f6223
https://github.com/scummvm/scummvm/commit/de952ae0b9226a67c8d20916e29f81258a2f6223
Author: Johannes Schickel (lordhoto at gmail.com)
Date: 2013-08-08T15:56:17-07:00
Commit Message:
Merge pull request #373 from lordhoto/ini-file
Rename ConfigFile to INIFile and remove outdated comments
Changed paths:
A common/ini-file.cpp
A common/ini-file.h
R common/config-file.cpp
R common/config-file.h
common/config-manager.h
common/module.mk
engines/composer/composer.h
engines/gob/iniconfig.cpp
engines/gob/iniconfig.h
engines/mohawk/livingbooks.cpp
engines/mohawk/livingbooks.h
engines/mohawk/livingbooks_lbx.cpp
engines/scumm/he/script_v80he.cpp
engines/testbed/config.cpp
engines/testbed/config.h
More information about the Scummvm-git-logs
mailing list