aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2004-03-28 20:28:45 +0000
committerMax Horn2004-03-28 20:28:45 +0000
commit09e3fec623c1ecea73a23d12891790569d1baa40 (patch)
tree2ecc5506966602daca62f36610cc9bd900e1f8b4 /common
parentdbda6299e1037db050634fe3b306779753f4bca8 (diff)
downloadscummvm-rg350-09e3fec623c1ecea73a23d12891790569d1baa40.tar.gz
scummvm-rg350-09e3fec623c1ecea73a23d12891790569d1baa40.tar.bz2
scummvm-rg350-09e3fec623c1ecea73a23d12891790569d1baa40.zip
Preserve comments in config files
svn-id: r13412
Diffstat (limited to 'common')
-rw-r--r--common/config-manager.cpp68
-rw-r--r--common/config-manager.h33
2 files changed, 72 insertions, 29 deletions
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 1dfd546e41..e19afeced0 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -115,15 +115,22 @@ void ConfigManager::loadFile(const String &filename) {
} else {
char buf[MAXLINELEN];
String domain;
+ String comment;
int lineno = 0;
+
+ // TODO: Detect if a domain occurs multiple times (or likewise, if
+ // a key occurs multiple times inside one domain).
while (!feof(cfg_file)) {
lineno++;
if (!fgets(buf, MAXLINELEN, cfg_file))
continue;
- if (!buf[0] || buf[0] == '#') {
- // Skip empty lines and comments
- // TODO: Comments should be preserved here!
+
+ if (buf[0] == '#') {
+ // Accumulate comments here. Once we encounter either the start
+ // of a new domain, or a key-value-pair, we associate the value
+ // of the 'comment' variable with that entity.
+ comment += buf;
} else if (buf[0] == '[') {
// It's a new domain which begins here.
char *p = buf + 1;
@@ -144,9 +151,17 @@ void ConfigManager::loadFile(const String &filename) {
default:
error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);
}
+
+ // Store domain comment
+ if (_globalDomains.contains(domain)) {
+ _globalDomains[domain].setDomainComment(comment);
+ } else {
+ _gameDomains[domain].setDomainComment(comment);
+ }
+ comment.clear();
} else {
- // Skip leading whitespaces
- char *t = ltrim(buf);
+ // Skip leading & trailing whitespaces
+ char *t = rtrim(ltrim(buf));
// Skip empty lines
if (*t == 0)
@@ -157,24 +172,22 @@ void ConfigManager::loadFile(const String &filename) {
error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);
}
- // It's a new key in the domain.
- char *p = strchr(t, '\n');
- if (p)
- *p = 0;
- p = strchr(t, '\r');
- if (p)
- *p = 0;
-
// Split string at '=' into 'key' and 'value'.
- p = strchr(t, '=');
- if (!p) {
+ char *p = strchr(t, '=');
+ if (!p)
error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
+ *p = 0;
+ String key = rtrim(t);
+ String value = ltrim(p + 1);
+ set(key, value, domain);
+
+ // Store comment
+ if (_globalDomains.contains(domain)) {
+ _globalDomains[domain].setKVComment(key, comment);
} else {
- *p = 0;
- String key = rtrim(t);
- String value = rtrim(ltrim(p + 1));
- set(key, value, domain);
+ _gameDomains[domain].setKVComment(key, comment);
}
+ comment.clear();
}
}
fclose(cfg_file);
@@ -211,13 +224,28 @@ void ConfigManager::writeDomain(FILE *file, const String &name, const Domain &do
if (domain.isEmpty())
return; // Don't bother writing empty domains.
+ String comment;
+
+ // Write domain comment (if any)
+ comment = domain.getDomainComment();
+ if (!comment.isEmpty())
+ fprintf(file, "%s", comment.c_str());
+
+ // Write domain start
fprintf(file, "[%s]\n", name.c_str());
+ // Write all key/value pairs in this domain, including comments
Domain::const_iterator x;
for (x = domain.begin(); x != domain.end(); ++x) {
const String &value = x->_value;
- if (!value.isEmpty())
+ if (!value.isEmpty()) {
+ // Write comment (if any)
+ comment = domain.getKVComment(x->_key);
+ if (!comment.isEmpty())
+ fprintf(file, "%s", comment.c_str());
+ // Write the key/value pair
fprintf(file, "%s=%s\n", x->_key.c_str(), value.c_str());
+ }
}
fprintf(file, "\n");
}
diff --git a/common/config-manager.h b/common/config-manager.h
index 604ccce111..3a54ccfb64 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -38,14 +38,9 @@ namespace Common {
* @todo Implement the callback based notification system (outline below)
* which sends out notifications to interested parties whenever the value
* of some specific (or any) configuration key changes.
- * @todo Store comments and write them back out to disk. A simple approach for
- * that would be to store comments which come before a section, and
- * comments which comes before a specific config key. While this is
- * limited, it is at least much better than not saving any comments, and
- * it shouldn't be hard to implement either.
- * @todo Allow preserving the order of the entries in the config file. Maybe
- * even add an API to query/modify that order, which could be used by the
- * launcher to allow arranging the game targets.
+ * @todo Preserve the order of the entries in the config file. Maybe even add
+ * an API to query/modify that order, which could be used by the launcher
+ * to allow arranging the game targets.
*/
class ConfigManager : public Singleton<ConfigManager> {
struct IgnoreCaseComparator {
@@ -53,12 +48,32 @@ class ConfigManager : public Singleton<ConfigManager> {
};
public:
- class Domain : public Map<String, String, IgnoreCaseComparator> {
+ typedef Map<String, String, IgnoreCaseComparator> StringMap;
+
+ class Domain : public StringMap {
+ private:
+ StringMap _keyValueComments;
+ String _domainComment;
public:
+
const String &get(const String &key) const {
Node *node = findNode(_root, key);
return node ? node->_value : String::emptyString;
}
+
+ void setDomainComment(const String &comment) {
+ _domainComment = comment;
+ }
+ const String &getDomainComment() const {
+ return _domainComment;
+ }
+
+ void setKVComment(const String &key, const String &comment) {
+ _keyValueComments[key] = comment;
+ }
+ const String &getKVComment(const String &key) const {
+ return _keyValueComments[key];
+ }
};
typedef Map<String, Domain, IgnoreCaseComparator> DomainMap;