src/lib/INIReader.cpp
branchv_0
changeset 23 b497140b0b63
parent 22 29d673a54ecf
child 24 07e0a2edf3bc
--- 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);
 	}