--- 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 {