YAML data to DOM: first dirty version with debug v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue, 27 Oct 2020 22:39:50 +0100
branchv_0
changeset 17 75c6685cceb9
parent 16 3b197bf7a231
child 18 737c507a3e32
YAML data to DOM: first dirty version with debug
src/XMLDocumentConstructor.h
--- a/src/XMLDocumentConstructor.h	Tue Oct 27 00:59:54 2020 +0100
+++ b/src/XMLDocumentConstructor.h	Tue Oct 27 22:39:50 2020 +0100
@@ -21,6 +21,7 @@
 namespace xmltable {
 
 #include <codecvt>
+#include <vector>
 
 #include <libxml++-2.6/libxml++/libxml++.h>
 #include <yaml.h>
@@ -31,13 +32,23 @@
 	xmlpp::DomParser* parser = nullptr;
 	yaml_parser_t yamlParser;
 
+	enum class Mode {
+		ROOT,
+		SEQUENCE,
+		MAPPING,
+		MAP_KEY
+	};
+
+	xmlpp::Element* current;
+	std::vector<Mode> mode;
+
 	static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) {
 		std::istream* input = ((XMLDocumentConstructor*) instance)->input;
 		input->read((char*) buffer, size);
 		*length = input->gcount();
 		return (input->good() || input->eof()) ? 1 : 0;
 	}
-	
+
 	/**
 	 * Both YAML and XML strings are in UTF-8.
 	 */
@@ -45,6 +56,16 @@
 		return value ? (const char*) value : "";
 	}
 
+	const std::string y2xname(yaml_char_t* value) {
+		// FIXME: escaping, assure valid XML names
+		//return std::string("name_") + y2x(value);
+		return y2x(value);
+	}
+
+	xmlpp::Element* parentOrSelf(xmlpp::Element* current) {
+		return current->get_parent() == nullptr ? current : current->get_parent();
+	}
+
 public:
 
 	XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
@@ -57,7 +78,8 @@
 	}
 
 	void process() {
-		xmlpp::Element* root = parser->get_document()->create_root_node("yaml");
+		current = parser->get_document()->create_root_node("yaml");
+		mode.push_back(Mode::ROOT);
 
 		while (true) {
 			yaml_event_t event;
@@ -70,34 +92,66 @@
 
 
 			if (event.type == YAML_STREAM_END_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_STREAM_END_EVENT");
+				std::cerr << "YAML_STREAM_END_EVENT" << std::endl;
 				yaml_event_delete(&event);
 				break;
 			} else if (event.type == YAML_STREAM_START_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_STREAM_START_EVENT");
+				std::cerr << "YAML_STREAM_START_EVENT" << std::endl;
 			} else if (event.type == YAML_NO_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_NO_EVENT");
+				std::cerr << "YAML_NO_EVENT" << std::endl;
+				current->add_child("null"); // TODO: null?
 			} else if (event.type == YAML_DOCUMENT_START_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_DOCUMENT_START_EVENT");
+				std::cerr << "YAML_DOCUMENT_START_EVENT" << std::endl;
 			} else if (event.type == YAML_DOCUMENT_END_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_DOCUMENT_END_EVENT");
+				std::cerr << "YAML_DOCUMENT_END_EVENT" << std::endl;
 			} else if (event.type == YAML_ALIAS_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_ALIAS_EVENT");
+				std::cerr << "YAML_ALIAS_EVENT" << std::endl;
+				// TODO: alias?
 			} else if (event.type == YAML_SCALAR_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_SCALAR_EVENT");
-				e->set_attribute("value", y2x(event.data.scalar.value));
-				e->set_attribute("anchor", y2x(event.data.scalar.anchor));
-				e->set_attribute("tag", y2x(event.data.scalar.tag));
-				e->set_attribute("style", std::to_string(event.data.scalar.style));
+				if (mode.back() == Mode::SEQUENCE) {
+					std::cerr << "YAML_SCALAR_EVENT: Mode::SEQUENCE: " << event.data.scalar.value << std::endl;
+					current->add_child("item")->add_child_text(y2x(event.data.scalar.value));
+				} else if (mode.back() == Mode::MAPPING) {
+					std::cerr << "YAML_SCALAR_EVENT: Mode::MAPPING: " << event.data.scalar.value << std::endl;
+					current = current->add_child(y2xname(event.data.scalar.value));
+					mode.push_back(Mode::MAP_KEY);
+				} else if (mode.back() == Mode::MAP_KEY) {
+					std::cerr << "YAML_SCALAR_EVENT: Mode::MAP_KEY: " << event.data.scalar.value << std::endl;
+					current->add_child_text(y2x(event.data.scalar.value));
+					current = parentOrSelf(current);
+					mode.pop_back();
+				} else {
+					std::cerr << "YAML_SCALAR_EVENT: ???" << std::endl;
+				}
+
 			} else if (event.type == YAML_SEQUENCE_START_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_SEQUENCE_START_EVENT");
-				e->set_attribute("style", std::to_string(event.data.sequence_start.style));
+				std::cerr << "YAML_SEQUENCE_START_EVENT" << std::endl;
+				if (mode.back() == Mode::MAP_KEY) mode.pop_back();
+				mode.push_back(Mode::SEQUENCE);
 			} else if (event.type == YAML_SEQUENCE_END_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_SEQUENCE_END_EVENT");
+				std::cerr << "YAML_SEQUENCE_END_EVENT" << std::endl;
+				current = parentOrSelf(current);
+				mode.pop_back(); // TODO: assert sequence?
 			} else if (event.type == YAML_MAPPING_START_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_MAPPING_START_EVENT");
+
+				if (mode.back() == Mode::SEQUENCE) {
+					std::cerr << "YAML_MAPPING_START_EVENT: Mode::SEQUENCE" << std::endl;
+					current = current->add_child("item");
+				} else if (mode.back() == Mode::MAP_KEY) {
+					std::cerr << "YAML_MAPPING_START_EVENT: Mode::MAP_KEY" << std::endl;
+					mode.pop_back();
+				} else {
+					std::cerr << "YAML_MAPPING_START_EVENT: Mode::?" << std::endl;
+					// TODO: map might be a key of another map → wrap/nest
+				}
+
+				mode.push_back(Mode::MAPPING);
 			} else if (event.type == YAML_MAPPING_END_EVENT) {
-				xmlpp::Element* e = root->add_child("YAML_MAPPING_END_EVENT");
+				std::cerr << "YAML_MAPPING_END_EVENT" << std::endl;
+				current = parentOrSelf(current);
+				mode.pop_back(); // TODO: assert map?
+			} else {
+				std::cerr << "???" << std::endl;
 			}
 
 			yaml_event_delete(&event);
@@ -109,4 +163,4 @@
 
 }
 }
-}
\ No newline at end of file
+}