src/INIWriter.h
branchv_0
changeset 5 bee7acb57330
parent 4 372b161669e4
child 8 7c85dc9a310b
--- a/src/INIWriter.h	Sat Dec 12 14:42:36 2020 +0100
+++ b/src/INIWriter.h	Sat Dec 12 19:52:38 2020 +0100
@@ -41,8 +41,26 @@
 	std::string commentSeparatorForEntries = " ; ";
 	std::string commentSeparatorStandalone = "; ";
 
+	relpipe::common::type::StringX hierarchySeparator = L"/";
+	bool allowSections = true;
+
 	bool hasContent = false;
 
+	std::vector<relpipe::common::type::StringX> currentSection;
+
+	relpipe::common::type::StringX getCurrentSectionFullName() {
+		std::wstringstream result;
+
+		// TODO: configurable hierarchy delimiter
+		// TODO: escape delimiter characters that are part of the section names
+		for (int i = 0; i < currentSection.size(); i++) {
+			if (i > 0)result << hierarchySeparator;
+			result << currentSection[i];
+		}
+
+		return result.str();
+	}
+
 	/**
 	 * TODO: use a common method
 	 */
@@ -176,7 +194,8 @@
 		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); // TODO: allow sections
+		else if (uri == option::HierarchySeparator) hierarchySeparator = value;
+		else if (uri == option::AllowSections) allowSections = parseBoolean(value);
 		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);
@@ -200,23 +219,32 @@
 	}
 
 	void endDocument() {
+		if (currentSection.size()) throw relpipe::reader::RelpipeReaderException(L"There are still " + std::to_wstring(currentSection.size()) + L" open sections during the endDocument() call. Need to call endSection() before.");
 		output.flush();
 	}
 
 	void startSection(const SectionStartEvent& event) {
-		if (hasContent) output << std::endl;
-		output << "[" << escape(event.name, EscapingProcessor::TextType::SectionName) << "]";
-		if (event.tag.size()) output << "[" << escape(event.tag, EscapingProcessor::TextType::SectionTag) << "]";
-		if (event.comment.size()) output << commentSeparatorForSections << escape(event.comment, EscapingProcessor::TextType::SectionComment);
-		output << std::endl;
+		currentSection.push_back(event.name);
+
+		if (allowSections) {
+			if (hasContent) output << std::endl;
+			output << "[" << escape(getCurrentSectionFullName(), EscapingProcessor::TextType::SectionName) << "]";
+			if (event.tag.size()) output << "[" << escape(event.tag, EscapingProcessor::TextType::SectionTag) << "]";
+			if (event.comment.size()) output << commentSeparatorForSections << escape(event.comment, EscapingProcessor::TextType::SectionComment);
+			output << std::endl;
+		}
+
 		hasContent = true;
 	}
 
 	void endSection() {
+		currentSection.pop_back();
 		output.flush();
 	}
 
 	void entry(const EntryEvent& event) {
+		// TODO: escape/quote parts separately + configurable quoting of parts or whole + the same for sub keys
+		if (!allowSections && currentSection.size()) output << escape(getCurrentSectionFullName(), EscapingProcessor::TextType::EntryKey) << convertor.to_bytes(hierarchySeparator);
 		output << escape(event.key, EscapingProcessor::TextType::EntryKey);
 		if (event.subKey.size()) output << "[" << escape(event.subKey, EscapingProcessor::TextType::EntrySubKey) << "]";
 		output << keyValueSeparator << escape(event.value, EscapingProcessor::TextType::EntryValue);