src/lib/INIReader.cpp
branchv_0
changeset 27 e9aad9dd823a
parent 26 b1f6fa3a6555
child 28 596a724fbb83
--- a/src/lib/INIReader.cpp	Sat Nov 28 00:46:40 2020 +0100
+++ b/src/lib/INIReader.cpp	Sat Nov 28 18:10:47 2020 +0100
@@ -32,6 +32,19 @@
 	std::istream& input;
 	std::vector<INIContentHandler*> handlers;
 
+	class ConfiguredUnescapingProcessor {
+	public:
+		std::shared_ptr<UnescapingProcessor> processor;
+		const std::string uri;
+		bool enbaled;
+
+		ConfiguredUnescapingProcessor(std::shared_ptr<UnescapingProcessor> processor, const std::string uri, bool enbaled) : processor(processor), uri(uri), enbaled(enbaled) {
+		}
+
+	};
+
+	std::vector<ConfiguredUnescapingProcessor> unescapingProcessors;
+
 	/** 
 	 * 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 „\“.
@@ -221,6 +234,12 @@
 		return result;
 	}
 
+	std::string unescape(const std::string& value, UnescapingProcessor::TextType type) {
+		std::string result = value;
+		for (ConfiguredUnescapingProcessor p : unescapingProcessors) if (p.enbaled) result = p.processor->unescape(result, type);
+		return result;
+	}
+
 	bool isComment(char ch) {
 		return oneOf(ch, commentSeparators);
 	}
@@ -268,6 +287,16 @@
 		}
 	}
 
+	bool setUnescaping(const std::string& uri, const std::string& value) {
+		for (ConfiguredUnescapingProcessor& p : unescapingProcessors) {
+			if (p.uri == uri) {
+				p.enbaled = parseBoolean(value);
+				return true;
+			}
+		}
+		return false;
+	}
+
 public:
 
 	INIReaderImpl(std::istream& input) : input(input) {
@@ -282,6 +311,7 @@
 		else if (uri == "key-value-separators") keyValueSeparators = value;
 		else if (uri == "quotes") quotes = value;
 		else if (uri == "dialect") setDialect(value);
+		else if (setUnescaping(uri, value));
 		else throw std::invalid_argument(std::string("Invalid parser option: „") + uri + "“ with value: „" + value + "“");
 	}
 
@@ -289,6 +319,10 @@
 		handlers.push_back(handler);
 	}
 
+	void addUnescapingProcessor(std::shared_ptr<UnescapingProcessor> processor, const std::string uri, bool enabledByDefault) override {
+		unescapingProcessors.push_back({processor, uri, enabledByDefault});
+	}
+
 	void process() override {
 		for (INIContentHandler* handler : handlers) handler->startDocument();
 
@@ -323,11 +357,13 @@
 				readAllWhitespace();
 				event.name = readTokenAndEatTerminator(']', &quote, &found);
 				if (!quote) event.name = trim(event.name);
+				event.name = unescape(event.name, UnescapingProcessor::TextType::SectionName);
 
 				readSpacesAndTabs();
 				if (allowSectionTags && peek() == '[') {
 					get();
 					event.tag = readTokenAndEatTerminator(']', &quote, &found);
+					event.tag = unescape(event.tag, UnescapingProcessor::TextType::SectionTag);
 				}
 
 				readSpacesAndTabs();
@@ -336,6 +372,7 @@
 					get();
 					readSpacesAndTabs();
 					event.comment = readUntil('\n', &found);
+					event.comment = unescape(event.comment, UnescapingProcessor::TextType::SectionComment);
 				} else if (ch == '\n') {
 					get();
 				} else {
@@ -350,6 +387,7 @@
 				get();
 				readSpacesAndTabs();
 				event.comment = readUntil('\n', &found);
+				event.comment = unescape(event.comment, UnescapingProcessor::TextType::Comment);
 				for (INIContentHandler* handler : handlers) handler->comment(event);
 			} else {
 				INIContentHandler::EntryEvent event;
@@ -380,9 +418,14 @@
 						event.key = match[1];
 						event.subKey = match[2];
 						event.fullKey = fullKey;
+						event.subKey = unescape(event.subKey, UnescapingProcessor::TextType::EntryKey);
 					}
 				}
 
+				event.key = unescape(event.key, UnescapingProcessor::TextType::EntryKey);
+				event.fullKey = unescape(event.fullKey, UnescapingProcessor::TextType::EntryKey);
+				event.value = unescape(event.value, UnescapingProcessor::TextType::EntryValue);
+
 				if (quote) {
 					readSpacesAndTabs();
 					ch = peek();
@@ -390,6 +433,7 @@
 						get();
 						readSpacesAndTabs();
 						event.comment = readUntil('\n', &found);
+						event.comment = unescape(event.comment, UnescapingProcessor::TextType::EntryComment);
 					} else if (ch == '\n') {
 						get();
 					} else {