implement --style standard v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 11 Dec 2020 12:34:42 +0100
branchv_0
changeset 2 e753a7f967c8
parent 1 e04e5bbc147b
child 3 ae8775e0bc7a
implement --style standard
src/INIStandardHandler.h
src/INIWriter.h
--- 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;
 	}