diff -r b1f6fa3a6555 -r e9aad9dd823a src/lib/BackspaceUnescapingProcessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/BackspaceUnescapingProcessor.h Sat Nov 28 18:10:47 2020 +0100 @@ -0,0 +1,70 @@ +/** + * Relational pipes + * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include "UnescapingProcessor.h" + +using namespace std; +using namespace relpipe::writer; + +namespace relpipe { +namespace in { +namespace ini { +namespace lib { + +class BackspaceUnescapingProcessor : public UnescapingProcessor { +private: + const bool lastEscaphingPhase = true; +public: + + std::string unescape(const std::string& s, const TextType type) override { + std::stringstream result; + for (int i = 0, length = s.size(); i < length; i++) { + char ch = s[i]; + if (i + 1 < length && ch == ESC) { + ch = s[i + 1]; + if (ch == ESC) put(result, ESC, i); // unescape \\ to \. + else if (lastEscaphingPhase) throw std::logic_error(std::string("Unsupported escape sequence: ") + ch); + else result.put(ESC); // keep the escape sequence for later unescaping phase + } else if (ch == ESC) { + throw std::logic_error(std::string("Missing escape sequence")); // this should not happen + } else { + result.put(ch); + } + } + return result.str(); + } + + /** + * @param lastEscaphingPhase whether this is final unescaping stage. + * By default it is set to true, thus no unrecognized escape sequences may left after this stage. + * Setting this to false is dangerous and may lead to errors and ambiguous behavior. + * It should be used only as a last resort. + * Because both "\\ \xxx" and "\ \xxx" will be converted to "\ \xxx" and the information will be lost. + * So, it is usually better to keep the "\" escaped as "\\" and process both the escaped backspaces and unrecognized escape sequences later. + */ + BackspaceUnescapingProcessor(bool lastEscaphingPhase = true) : lastEscaphingPhase(lastEscaphingPhase) { + } + +}; + +} +} +} +}