src/INIWriter.h
branchv_0
changeset 4 372b161669e4
parent 3 ae8775e0bc7a
child 5 bee7acb57330
--- a/src/INIWriter.h	Sat Dec 12 00:01:57 2020 +0100
+++ b/src/INIWriter.h	Sat Dec 12 14:42:36 2020 +0100
@@ -18,6 +18,7 @@
 
 #include <string>
 #include <sstream>
+#include <regex>
 
 #include <relpipe/common/type/typedefs.h>
 #include <relpipe/reader/RelpipeReaderException.h>
@@ -51,10 +52,43 @@
 		else throw relpipe::reader::RelpipeReaderException(L"Unable to parse boolean value: " + value + L" (expecting true or false)");
 	}
 
+	EscapingProcessor::QuotingType parseQuotingType(const relpipe::common::type::StringX& value) {
+		if (value == quoting::None) return EscapingProcessor::QuotingType::None;
+		else if (value == quoting::Apostrophes) return EscapingProcessor::QuotingType::Apostrophes;
+		else if (value == quoting::Quotes) return EscapingProcessor::QuotingType::Quotes;
+		else throw relpipe::reader::RelpipeReaderException(L"Unsupported quoting type:" + value);
+	}
+
+	class QuotingRule {
+	public:
+		EscapingProcessor::QuotingType type = EscapingProcessor::QuotingType::None;
+		relpipe::common::type::StringX pattern;
+
+		EscapingProcessor::QuotingType findEffectiveQuotingType(const relpipe::common::type::StringX& value) {
+			if (type == EscapingProcessor::QuotingType::None) return type;
+			else if (pattern.empty()) return type;
+			else return std::regex_match(value, std::wregex(pattern)) ? type : EscapingProcessor::QuotingType::None;
+		}
+	};
+
+	QuotingRule quotingForSections;
+	QuotingRule quotingForKeys;
+	QuotingRule quotingForValues;
+
 	std::string escape(const relpipe::common::type::StringX& value, EscapingProcessor::TextType type) {
 		relpipe::common::type::StringX result = value;
-		EscapingProcessor::QuotingType quotingType = EscapingProcessor::QuotingType::None;
+
+		EscapingProcessor::QuotingType quotingType;
+		if (type == EscapingProcessor::TextType::SectionName || type == EscapingProcessor::TextType::SectionTag) quotingType = quotingForSections.findEffectiveQuotingType(value);
+		else if (type == EscapingProcessor::TextType::EntryKey || type == EscapingProcessor::TextType::EntrySubKey) quotingType = quotingForKeys.findEffectiveQuotingType(value);
+		else if (type == EscapingProcessor::TextType::EntryValue) quotingType = quotingForValues.findEffectiveQuotingType(value);
+		else quotingType = EscapingProcessor::QuotingType::None;
+
 		for (ConfiguredEscapingProcessor p : escapingProcessors) if (p.enbaled) result = p.processor->escape(result, type, quotingType);
+
+		if (quotingType == EscapingProcessor::QuotingType::Quotes) result = L"\"" + result + L"\"";
+		else if (quotingType == EscapingProcessor::QuotingType::Apostrophes) result = L"'" + result + L"'";
+
 		return convertor.to_bytes(result);
 	}
 
@@ -137,14 +171,18 @@
 	};
 
 	void setOption(relpipe::common::type::StringX uri, relpipe::common::type::StringX value) {
-		// TODO: setOption(): escaping, quotes, allow-sections
 		if (uri == option::Dialect) setDialect(value);
 		else if (uri == option::CommentSeparatorForSections) commentSeparatorForSections = convertor.to_bytes(value);
 		else if (uri == option::CommentSeparatorForEntries) commentSeparatorForEntries = convertor.to_bytes(value);
 		else if (uri == option::CommentSeparatorStandalone) commentSeparatorStandalone = convertor.to_bytes(value);
 		else if (uri == option::KeyValueSeparator) keyValueSeparator = convertor.to_bytes(value);
-		else if (uri == option::AllowSections);
-		else if (uri == option::Quotes);
+		else if (uri == option::AllowSections); // TODO: allow sections
+		else if (uri == option::QuotesTypeForSections) quotingForSections.type = parseQuotingType(value);
+		else if (uri == option::QuotesTypeForKeys) quotingForKeys.type = parseQuotingType(value);
+		else if (uri == option::QuotesTypeForValues) quotingForValues.type = parseQuotingType(value);
+		else if (uri == option::QuotesPatternForSections) quotingForSections.pattern = value;
+		else if (uri == option::QuotesPatternForKeys) quotingForKeys.pattern = value;
+		else if (uri == option::QuotesPatternForValues) quotingForValues.pattern = value;
 		else if (setEscaping(uri, value));
 		else throw relpipe::reader::RelpipeReaderException(L"Unsupported writer option: " + uri);
 	}