--- a/bash-completion.sh Sat Dec 12 00:01:57 2020 +0100
+++ b/bash-completion.sh Sat Dec 12 14:42:36 2020 +0100
@@ -40,6 +40,12 @@
"java-manifest-mf"
);
+ QUOTING_TYPES=(
+ "none"
+ "apostrophes"
+ "quotes"
+ )
+
WRITER_OPTIONS=(
"dialect"
"comment-separator-for-sections"
@@ -49,6 +55,12 @@
"escape-backspace"
"escape-basic"
"escape-java-properties"
+ "quotes-type-for-sections"
+ "quotes-type-for-keys"
+ "quotes-type-for-values"
+ "quotes-pattern-for-sections"
+ "quotes-pattern-for-keys"
+ "quotes-pattern-for-values"
);
@@ -63,6 +75,9 @@
elif [[ "$w2" == "--writer-option" && "$w1" == "escape-backspace" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
elif [[ "$w2" == "--writer-option" && "$w1" == "escape-basic" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
elif [[ "$w2" == "--writer-option" && "$w1" == "escape-java-properties" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-sections" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-keys" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-values" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
elif [[ "$w2" == "--writer-option" && "x$w0" == "x" ]]; then COMPREPLY=("''")
else
--- a/src/BasicEscapingProcessor.h Sat Dec 12 00:01:57 2020 +0100
+++ b/src/BasicEscapingProcessor.h Sat Dec 12 14:42:36 2020 +0100
@@ -41,6 +41,7 @@
else if (ch == L'\t') result.put(ESC).put(L't');
else if (ch == L'"' && quotingType != QuotingType::Apostrophes) result.put(ESC).put(ch);
else if (ch == L'\'' && quotingType != QuotingType::Quotes) result.put(ESC).put(ch);
+ else if (ch == L'=' && quotingType == QuotingType::None) result.put(ESC).put(ch);
else result.put(ch);
}
--- 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);
}
--- a/src/JavaPropertiesDialect.h Sat Dec 12 00:01:57 2020 +0100
+++ b/src/JavaPropertiesDialect.h Sat Dec 12 14:42:36 2020 +0100
@@ -30,7 +30,9 @@
void apply(INIWriter& writer) override {
writer.setOption(option::AllowSections, L"false");
- writer.setOption(option::Quotes, L"");
+ writer.setOption(option::QuotesTypeForSections, quoting::None);
+ writer.setOption(option::QuotesTypeForKeys, quoting::None);
+ writer.setOption(option::QuotesTypeForValues, quoting::None);
writer.setOption(option::KeyValueSeparator, L"=");
writer.setOption(option::CommentSeparatorForSections, L"");
writer.setOption(option::CommentSeparatorForEntries, L"");
--- a/src/uri.h Sat Dec 12 00:01:57 2020 +0100
+++ b/src/uri.h Sat Dec 12 14:42:36 2020 +0100
@@ -31,7 +31,12 @@
static const wchar_t* CommentSeparatorForEntries = L"comment-separator-for-entries";
static const wchar_t* CommentSeparatorStandalone = L"comment-separator-standalone";
static const wchar_t* KeyValueSeparator = L"key-value-separator";
-static const wchar_t* Quotes = L"quotes";
+static const wchar_t* QuotesTypeForSections = L"quotes-type-for-sections";
+static const wchar_t* QuotesTypeForKeys = L"quotes-type-for-keys";
+static const wchar_t* QuotesTypeForValues = L"quotes-type-for-values";
+static const wchar_t* QuotesPatternForSections = L"quotes-pattern-for-sections";
+static const wchar_t* QuotesPatternForKeys = L"quotes-pattern-for-keys";
+static const wchar_t* QuotesPatternForValues = L"quotes-pattern-for-values";
static const wchar_t* Dialect = L"dialect";
}
@@ -42,6 +47,13 @@
static const wchar_t* Backspace = L"escape-backspace";
}
+/** not options but a values of the quotes-type-for-* options */
+namespace quoting {
+static const wchar_t* None = L"none";
+static const wchar_t* Apostrophes = L"apostrophes";
+static const wchar_t* Quotes = L"quotes";
+}
+
/** not options but a values of the dialect option */
namespace dialect {
static const wchar_t* JavaProperties = L"java-properties";