produce hierarchical structure of INI sections and entries v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 22 Nov 2020 19:25:42 +0100
branchv_0
changeset 18 45c06bdf9045
parent 17 786977554fc3
child 19 90f2b8ca32bf
produce hierarchical structure of INI sections and entries
src/XMLDocumentConstructor.h
--- a/src/XMLDocumentConstructor.h	Sun Nov 22 17:39:10 2020 +0100
+++ b/src/XMLDocumentConstructor.h	Sun Nov 22 19:25:42 2020 +0100
@@ -16,6 +16,7 @@
  */
 #pragma once
 
+#include <stdexcept>
 #include <libxml++-2.6/libxml++/libxml++.h>
 
 #include "lib/INIReader.h"
@@ -28,7 +29,8 @@
 class HierarchicalINIContentHandler : public INIContentHandler {
 private:
 	xmlpp::DomParser* domParser;
-	wstring_convert < codecvt_utf8<wchar_t>> convertor; // INI parser works with UTF-8
+	XMLNameCodec nameCodec;
+	xmlpp::Element* currentSection = nullptr;
 public:
 
 	HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) {
@@ -38,40 +40,43 @@
 	}
 
 	void startDocument() override {
-		domParser->get_document()->create_root_node("ini");
-		domParser->get_document()->get_root_node()->add_child("startDocument");
-		// there should be only one document
+		if (currentSection) throw std::out_of_range("Lunatic INI parser send us multiple documents.");
+		currentSection = domParser->get_document()->create_root_node("ini");
 	};
 
 	void endDocument() override {
-		domParser->get_document()->get_root_node()->add_child("endDocument");
 	};
 
 	void startSection(const SectionStartEvent& event) override {
-		xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("startSection");
-		node->add_child("name")->add_child_text(event.name);
-		node->add_child("comment")->add_child_text(event.comment);
-		node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber));
-		node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber));
+		currentSection = currentSection->add_child(nameCodec.encode(event.name));
+		currentSection->set_attribute("type", "section");
+		currentSection->set_attribute("name", event.name);
+		if (event.comment.size()) currentSection->set_attribute("comment", event.comment);
+		if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber));
+		if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber));
 	};
 
 	void endSection() override {
-		domParser->get_document()->get_root_node()->add_child("endSection");
+		currentSection = currentSection->get_parent();
+		if (currentSection == nullptr) throw std::out_of_range("Lunatic INI parser tried to end a section without starting it before.");
 	};
 
 	void entry(const EntryEvent& event) override {
-		xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("entry");
-		node->add_child("key")->add_child_text(event.key);
-		node->add_child("sub-key")->add_child_text(event.subKey);
-		node->add_child("full-key")->add_child_text(event.fullKey);
-		node->add_child("value")->add_child_text(event.value);
-		node->add_child("comment")->add_child_text(event.comment);
-		node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber));
-		node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber));
+		xmlpp::Element* entry = currentSection->add_child(nameCodec.encode(event.fullKey));
+		entry->set_attribute("type", "entry");
+		entry->set_attribute("key", event.key);
+		entry->set_attribute("full-key", event.fullKey);
+		if (event.subKey.size()) entry->set_attribute("sub-key", event.subKey);
+		if (event.comment.size()) currentSection->set_attribute("comment", event.comment);
+		if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber));
+		if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber));
+		entry->add_child_text(event.value);
 	};
 
 };
 
+// TODO: support also other styles/mappings e.g. <section/> and <entry/> with INI names only in the XML attributes (and thus without @type="section|entry")
+
 class XMLDocumentConstructor {
 private:
 	std::istream* input = nullptr;