src/INIWriter.h
branchv_0
changeset 4 372b161669e4
parent 3 ae8775e0bc7a
child 5 bee7acb57330
equal deleted inserted replaced
3:ae8775e0bc7a 4:372b161669e4
    16  */
    16  */
    17 #pragma once
    17 #pragma once
    18 
    18 
    19 #include <string>
    19 #include <string>
    20 #include <sstream>
    20 #include <sstream>
       
    21 #include <regex>
    21 
    22 
    22 #include <relpipe/common/type/typedefs.h>
    23 #include <relpipe/common/type/typedefs.h>
    23 #include <relpipe/reader/RelpipeReaderException.h>
    24 #include <relpipe/reader/RelpipeReaderException.h>
    24 
    25 
    25 #include "uri.h"
    26 #include "uri.h"
    49 		if (value == L"true") return true;
    50 		if (value == L"true") return true;
    50 		else if (value == L"false") return false;
    51 		else if (value == L"false") return false;
    51 		else throw relpipe::reader::RelpipeReaderException(L"Unable to parse boolean value: " + value + L" (expecting true or false)");
    52 		else throw relpipe::reader::RelpipeReaderException(L"Unable to parse boolean value: " + value + L" (expecting true or false)");
    52 	}
    53 	}
    53 
    54 
       
    55 	EscapingProcessor::QuotingType parseQuotingType(const relpipe::common::type::StringX& value) {
       
    56 		if (value == quoting::None) return EscapingProcessor::QuotingType::None;
       
    57 		else if (value == quoting::Apostrophes) return EscapingProcessor::QuotingType::Apostrophes;
       
    58 		else if (value == quoting::Quotes) return EscapingProcessor::QuotingType::Quotes;
       
    59 		else throw relpipe::reader::RelpipeReaderException(L"Unsupported quoting type:" + value);
       
    60 	}
       
    61 
       
    62 	class QuotingRule {
       
    63 	public:
       
    64 		EscapingProcessor::QuotingType type = EscapingProcessor::QuotingType::None;
       
    65 		relpipe::common::type::StringX pattern;
       
    66 
       
    67 		EscapingProcessor::QuotingType findEffectiveQuotingType(const relpipe::common::type::StringX& value) {
       
    68 			if (type == EscapingProcessor::QuotingType::None) return type;
       
    69 			else if (pattern.empty()) return type;
       
    70 			else return std::regex_match(value, std::wregex(pattern)) ? type : EscapingProcessor::QuotingType::None;
       
    71 		}
       
    72 	};
       
    73 
       
    74 	QuotingRule quotingForSections;
       
    75 	QuotingRule quotingForKeys;
       
    76 	QuotingRule quotingForValues;
       
    77 
    54 	std::string escape(const relpipe::common::type::StringX& value, EscapingProcessor::TextType type) {
    78 	std::string escape(const relpipe::common::type::StringX& value, EscapingProcessor::TextType type) {
    55 		relpipe::common::type::StringX result = value;
    79 		relpipe::common::type::StringX result = value;
    56 		EscapingProcessor::QuotingType quotingType = EscapingProcessor::QuotingType::None;
    80 
       
    81 		EscapingProcessor::QuotingType quotingType;
       
    82 		if (type == EscapingProcessor::TextType::SectionName || type == EscapingProcessor::TextType::SectionTag) quotingType = quotingForSections.findEffectiveQuotingType(value);
       
    83 		else if (type == EscapingProcessor::TextType::EntryKey || type == EscapingProcessor::TextType::EntrySubKey) quotingType = quotingForKeys.findEffectiveQuotingType(value);
       
    84 		else if (type == EscapingProcessor::TextType::EntryValue) quotingType = quotingForValues.findEffectiveQuotingType(value);
       
    85 		else quotingType = EscapingProcessor::QuotingType::None;
       
    86 
    57 		for (ConfiguredEscapingProcessor p : escapingProcessors) if (p.enbaled) result = p.processor->escape(result, type, quotingType);
    87 		for (ConfiguredEscapingProcessor p : escapingProcessors) if (p.enbaled) result = p.processor->escape(result, type, quotingType);
       
    88 
       
    89 		if (quotingType == EscapingProcessor::QuotingType::Quotes) result = L"\"" + result + L"\"";
       
    90 		else if (quotingType == EscapingProcessor::QuotingType::Apostrophes) result = L"'" + result + L"'";
       
    91 
    58 		return convertor.to_bytes(result);
    92 		return convertor.to_bytes(result);
    59 	}
    93 	}
    60 
    94 
    61 	class ConfiguredEscapingProcessor {
    95 	class ConfiguredEscapingProcessor {
    62 	public:
    96 	public:
   135 
   169 
   136 	virtual ~INIWriter() {
   170 	virtual ~INIWriter() {
   137 	};
   171 	};
   138 
   172 
   139 	void setOption(relpipe::common::type::StringX uri, relpipe::common::type::StringX value) {
   173 	void setOption(relpipe::common::type::StringX uri, relpipe::common::type::StringX value) {
   140 		// TODO: setOption(): escaping, quotes, allow-sections
       
   141 		if (uri == option::Dialect) setDialect(value);
   174 		if (uri == option::Dialect) setDialect(value);
   142 		else if (uri == option::CommentSeparatorForSections) commentSeparatorForSections = convertor.to_bytes(value);
   175 		else if (uri == option::CommentSeparatorForSections) commentSeparatorForSections = convertor.to_bytes(value);
   143 		else if (uri == option::CommentSeparatorForEntries) commentSeparatorForEntries = convertor.to_bytes(value);
   176 		else if (uri == option::CommentSeparatorForEntries) commentSeparatorForEntries = convertor.to_bytes(value);
   144 		else if (uri == option::CommentSeparatorStandalone) commentSeparatorStandalone = convertor.to_bytes(value);
   177 		else if (uri == option::CommentSeparatorStandalone) commentSeparatorStandalone = convertor.to_bytes(value);
   145 		else if (uri == option::KeyValueSeparator) keyValueSeparator = convertor.to_bytes(value);
   178 		else if (uri == option::KeyValueSeparator) keyValueSeparator = convertor.to_bytes(value);
   146 		else if (uri == option::AllowSections);
   179 		else if (uri == option::AllowSections); // TODO: allow sections
   147 		else if (uri == option::Quotes);
   180 		else if (uri == option::QuotesTypeForSections) quotingForSections.type = parseQuotingType(value);
       
   181 		else if (uri == option::QuotesTypeForKeys) quotingForKeys.type = parseQuotingType(value);
       
   182 		else if (uri == option::QuotesTypeForValues) quotingForValues.type = parseQuotingType(value);
       
   183 		else if (uri == option::QuotesPatternForSections) quotingForSections.pattern = value;
       
   184 		else if (uri == option::QuotesPatternForKeys) quotingForKeys.pattern = value;
       
   185 		else if (uri == option::QuotesPatternForValues) quotingForValues.pattern = value;
   148 		else if (setEscaping(uri, value));
   186 		else if (setEscaping(uri, value));
   149 		else throw relpipe::reader::RelpipeReaderException(L"Unsupported writer option: " + uri);
   187 		else throw relpipe::reader::RelpipeReaderException(L"Unsupported writer option: " + uri);
   150 	}
   188 	}
   151 
   189 
   152 	void addDialect(std::shared_ptr<Dialect> dialect, const relpipe::common::type::StringX uri, bool enabledByDefault) {
   190 	void addDialect(std::shared_ptr<Dialect> dialect, const relpipe::common::type::StringX uri, bool enabledByDefault) {