--- 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);
}