--- a/src/lib/INIReader.cpp Thu Nov 26 18:52:49 2020 +0100
+++ b/src/lib/INIReader.cpp Fri Nov 27 16:29:12 2020 +0100
@@ -33,8 +33,6 @@
std::vector<INIContentHandler*> handlers;
/**
- * This might be configurable.
- *
* By default, we ignore all leading whitespace on continuing lines.
* If there should be some spaces or tabs, they should be placed on the previous line before the „\“.
* If a line break is desired, it should be written as \n (escaped) or the value should be quoted in " or '.
@@ -42,11 +40,9 @@
* Related specifications:
* - https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Properties.html
*/
- bool consumeLeadingSpacesOnContinuingLines = true;
+ bool trimLeadingSpacesOnContinuingLines = true;
/**
- * This might be configurable.
- *
* KDE uses some weird INI dialect that allows [section][x] syntax where „x“ is kind of „tag“ that signalizes some properties of given section.
* Line „[section_1][$i]“ means that the „section_1“ is „locked“.
* We may emit this information somehow later, but for now, it is just ignored.
@@ -59,8 +55,6 @@
bool allowSectionTags = true;
/**
- * This might be configurable.
- *
* If whole key is „aaa[bbb]“ then „aaa“ is considered to be the key and „bbb“ the sub-key.
* No \[ escaping is currently supported, so the key might not contain the bracket character.
*
@@ -71,8 +65,6 @@
bool allowSubKeys = true;
/**
- * This might be configurable.
- *
* Classic INI uses „key=value“ syntax.
* But some other formats/dialects might use key:value.
*
@@ -83,8 +75,6 @@
std::string keyValueSeparators = "=";
/**
- * This might be configurable.
- *
* Classic INI uses „; comment“ syntax.
* But many existing files contain „# comment“ lines.
*
@@ -93,8 +83,6 @@
std::string commentSeparators = ";#";
/**
- * This might be configurable.
- *
* INI often support both "quotes" and 'apostrophes' styles.
* But some dialects may support only one of them or not support quoting at all.
*
@@ -146,7 +134,7 @@
}
void processContinuingLine(std::stringstream& result) {
- if (consumeLeadingSpacesOnContinuingLines) readSpacesAndTabs();
+ if (trimLeadingSpacesOnContinuingLines) readSpacesAndTabs();
else result.put('\n');
}
@@ -237,11 +225,49 @@
return std::regex_replace(s, std::regex("^\\s+|\\s+$"), "");
}
+ /**
+ * TODO: use a common method
+ */
+ bool parseBoolean(const std::string& value) {
+ if (value == "true") return true;
+ else if (value == "false") return false;
+ else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
+ }
+
+ void setDialect(const std::string& name) {
+ if (name == "default-ini") {
+ // already set
+ } else if (name == "java-properties") {
+ trimLeadingSpacesOnContinuingLines = true;
+ allowSectionTags = false;
+ allowSubKeys = false;
+ commentSeparators = "#";
+ keyValueSeparators = "=:";
+ quotes = "";
+ // TODO: allowSections = false;
+ // TODO: enable unicode unescaping
+ } else {
+ throw std::invalid_argument(std::string("Unsupported INI dialect: ") + name);
+ }
+ }
+
public:
INIReaderImpl(std::istream& input) : input(input) {
}
+ void setOption(const std::string& uri, const std::string& value) override {
+ if (uri == "trim-continuing-lines") trimLeadingSpacesOnContinuingLines = parseBoolean(value); // TODO: continuing lines modes (enum), not just boolean
+ // TODO: else if (uri == "allow-sections") allowSections = parseBoolean(value);
+ else if (uri == "allow-section-tags") allowSectionTags = parseBoolean(value);
+ else if (uri == "allow-sub-keys") allowSubKeys = parseBoolean(value);
+ else if (uri == "comment-separators") commentSeparators = value;
+ else if (uri == "key-value-separators") keyValueSeparators = value;
+ else if (uri == "quotes") quotes = value;
+ else if (uri == "dialect") setDialect(value);
+ else throw std::invalid_argument(std::string("Invalid parser option: „") + uri + "“ with value: „" + value + "“");
+ }
+
void addHandler(INIContentHandler* handler) override {
handlers.push_back(handler);
}