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