RelpipeASN1ContentHandler: first version that parses a single relation v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 26 Jul 2021 21:25:48 +0200
branchv_0
changeset 5 f913370404eb
parent 4 368ba99bb98f
child 6 523c9c39c996
RelpipeASN1ContentHandler: first version that parses a single relation
src/RelpipeASN1ContentHandler.h
--- a/src/RelpipeASN1ContentHandler.h	Sun Jul 25 18:22:07 2021 +0200
+++ b/src/RelpipeASN1ContentHandler.h	Mon Jul 26 21:25:48 2021 +0200
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <relpipe/writer/RelationalWriter.h>
+#include <relpipe/writer/RelpipeWriterException.h>
 #include "lib/ASN1ContentHandler.h"
 #include "Configuration.h"
 
@@ -30,6 +31,28 @@
 	std::shared_ptr<relpipe::writer::RelationalWriter> writer;
 	Configuration configuration;
 
+	relpipe::common::type::StringX currentRelationName;
+	std::vector<relpipe::writer::AttributeMetadata> currentAttributes;
+
+	enum class State {
+		Start,
+		Relation,
+		RelationName,
+		Header,
+		HeaderItem,
+		AttributeName,
+		AttributeType,
+		Records,
+		Record,
+		Attribute,
+	};
+
+	State state = State::Start;
+
+	void assertTag(const Header& header, uint64_t expectedTag, TagClass expectedClass = TagClass::Universal) {
+		if (header.tagClass != expectedClass || header.tag != expectedTag) throw relpipe::writer::RelpipeWriterException(L"Unexpected tag."); // TODO: add actual vs. expected values
+	}
+
 public:
 
 	RelpipeASN1ContentHandler(std::shared_ptr<relpipe::writer::RelationalWriter> writer, Configuration configuration) : writer(writer), configuration(configuration) {
@@ -46,21 +69,43 @@
 	}
 
 	void writeCollectionStart(const Header& header) override {
+		assertTag(header, lib::UniversalType::Sequence);
+		if (state == State::Start) state = State::Relation;
+		else if (state == State::Relation) state = State::RelationName;
+		else if (state == State::Header) state = State::HeaderItem;
+		else if (state == State::HeaderItem) state = State::AttributeName;
+		else if (state == State::Records) state = State::Record;
+		else std::wcerr << L"writeCollectionStart(): state=" << (int) state << std::endl; // TODO: remove
 	}
 
 	void writeCollectionEnd() override {
+		if (state == State::Header) state = State::Records;
+		else if (state == State::AttributeType) state = State::HeaderItem;
+		else if (state == State::HeaderItem) state = State::Records;
+		else if (state == State::Records) state = State::Relation;
+		else if (state == State::Record) state = State::Record;
+		else std::wcerr << L"writeCollectionEnd(): state=" << (int) state << std::endl; // TODO: remove
+		
+		if (state == State::Records) {
+			writer->startRelation(currentRelationName, currentAttributes, true);
+			currentRelationName = L"";
+			currentAttributes.clear();
+		}
 	}
 
 	void writeBitString(const Header& header, std::vector<bool> value) override {
 	}
 
 	void writeBoolean(const Header& header, bool value) override {
+		if (state == State::Record) writer->writeAttribute(&value, typeid (value));
 	}
 
 	void writeDateTime(const Header& header, DateTime value) override {
 	}
 
 	void writeInteger(const Header& header, Integer value) override {
+		relpipe::common::type::Integer integer = value.toInt64();
+		if (state == State::Record) writer->writeAttribute(&integer, typeid (integer));
 	}
 
 	void writeNull(const Header& header) override {
@@ -73,6 +118,20 @@
 	}
 
 	void writeTextString(const Header& header, std::string value) override {
+		assertTag(header, lib::UniversalType::UTF8String);
+		relpipe::common::type::StringX str = convertor.from_bytes(value);
+
+		if (state == State::RelationName) {
+			currentRelationName = convertor.from_bytes(value);
+			state = State::Header;
+		} else if (state == State::AttributeName) {
+			currentAttributes.push_back({str, relpipe::writer::TypeId::STRING});
+			state = State::AttributeType;
+		} else if (state == State::AttributeType) {
+			currentAttributes.back().typeId = writer->toTypeId(str);
+		} else if (state == State::Record) {
+			writer->writeAttribute(&str, typeid (str));
+		} else std::wcerr << L"writeTextString(): state=" << (int) state << std::endl; // TODO: remove
 	}
 
 	void writeSpecific(const Header& header, std::string value) override {