diff -r 368ba99bb98f -r f913370404eb 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 +#include #include "lib/ASN1ContentHandler.h" #include "Configuration.h" @@ -30,6 +31,28 @@ std::shared_ptr writer; Configuration configuration; + relpipe::common::type::StringX currentRelationName; + std::vector 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 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 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 {