diff -r b1f6fa3a6555 -r e9aad9dd823a src/lib/INIReader.cpp --- 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 handlers; + class ConfiguredUnescapingProcessor { + public: + std::shared_ptr processor; + const std::string uri; + bool enbaled; + + ConfiguredUnescapingProcessor(std::shared_ptr processor, const std::string uri, bool enbaled) : processor(processor), uri(uri), enbaled(enbaled) { + } + + }; + + std::vector 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 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(']', "e, &found); if (!quote) event.name = trim(event.name); + event.name = unescape(event.name, UnescapingProcessor::TextType::SectionName); readSpacesAndTabs(); if (allowSectionTags && peek() == '[') { get(); event.tag = readTokenAndEatTerminator(']', "e, &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 {