--- a/src/INIStandardHandler.h Wed Dec 09 23:53:30 2020 +0100
+++ b/src/INIStandardHandler.h Fri Dec 11 12:34:42 2020 +0100
@@ -39,22 +39,80 @@
class INIStandardHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
private:
INIWriter& writer;
+ size_t currentAttributeIndex = 0;
+ std::vector<relpipe::reader::handlers::AttributeMetadata> currentAttributes;
+ relpipe::common::type::StringX previousSection;
+ relpipe::common::type::StringX currentSection;
+ relpipe::common::type::StringX currentKey;
+ relpipe::common::type::StringX currentSubKey;
+ relpipe::common::type::StringX currentValue;
+ relpipe::common::type::StringX currentComment;
+ relpipe::common::type::StringX currentWhitespace;
+ bool hasSections = false;
public:
INIStandardHandler(INIWriter& writer) : writer(writer) {
}
virtual ~INIStandardHandler() {
-
}
void startRelation(relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
+ currentAttributes = attributes;
+ currentSection.clear();
+ currentKey.clear();
+ currentSubKey.clear();
+ currentValue.clear();
+ currentComment.clear();
+ currentWhitespace.clear();
}
void attribute(const relpipe::common::type::StringX& value) override {
+ auto name = currentAttributes[currentAttributeIndex % currentAttributes.size()].getAttributeName();
+ if (name == L"section") currentSection = value;
+ else if (name == L"key") currentKey = value;
+ else if (name == L"sub_key") currentSubKey = value;
+ else if (name == L"value") currentValue = value;
+ else if (name == L"comment") currentComment = value;
+ else if (name == L"whitespace") currentWhitespace = value;
+
+ currentAttributeIndex++;
+
+ if (currentAttributeIndex == currentAttributes.size()) {
+ currentAttributeIndex = 0;
+
+ if (currentSection != previousSection) {
+ if (previousSection.size()) writer.endSection();
+ writer.startSection({
+ .comment = currentKey.empty() ? currentComment : L"",
+ .name = currentSection,
+ .tag = L"",
+ });
+ previousSection = currentSection;
+ hasSections = true;
+ }
+
+ if (currentKey.size()) {
+ writer.entry({
+ .comment = currentComment,
+ .key = currentKey,
+ .subKey = currentSubKey,
+ .value = currentValue,
+ });
+ } else if (currentComment.size()) {
+ writer.comment({
+ .comment = currentComment,
+ });
+ } else if (currentWhitespace.size()) {
+ writer.whitespace({
+ .whitespace = currentWhitespace,
+ });
+ }
+ }
}
void endOfPipe() {
+ if (hasSections) writer.endSection();
}
};
--- a/src/INIWriter.h Wed Dec 09 23:53:30 2020 +0100
+++ b/src/INIWriter.h Fri Dec 11 12:34:42 2020 +0100
@@ -35,6 +35,8 @@
std::string commentSeparatorForSections = " ; ";
std::string commentSeparatorForEntries = " ; ";
std::string commentSeparatorStandalone = "; ";
+
+ bool hasContent = false;
enum class TokenType {
SectionName,
@@ -117,14 +119,15 @@
}
void startSection(const SectionStartEvent& event) {
+ if (hasContent) output << std::endl;
output << "[" << escape(TokenType::SectionName, event.name) << "]";
if (event.tag.size()) output << "[" << escape(TokenType::SectionTag, event.tag) << "]";
if (event.comment.size()) output << commentSeparatorForSections << escape(TokenType::SectionComment, event.comment);
output << std::endl;
+ hasContent = true;
}
void endSection() {
- output << std::endl;
output.flush();
}
@@ -134,10 +137,13 @@
output << keyValueSeparator << escape(TokenType::EntryValue, event.value);
if (event.comment.size()) output << commentSeparatorForEntries << escape(TokenType::EntryComment, event.comment);
output << std::endl;
+ hasContent = true;
}
void comment(const CommentEvent& event) {
output << commentSeparatorStandalone << escape(TokenType::StandaloneComment, event.comment);
+ output << std::endl;
+ hasContent = true;
}
void whitespace(const WhitespaceEvent& event) {
@@ -148,6 +154,7 @@
else if (ch == L'\r'); // TODO: keep CR?
else; // TODO: throw exception if whitespace contains unexpected data? (should not happen)
}
+ hasContent = true;
}