diff -r 9005fdd81bca -r 1b4ca23e5d04 src/RecfileHandler.h --- a/src/RecfileHandler.h Sat Mar 30 01:12:42 2019 +0100 +++ b/src/RecfileHandler.h Sat Mar 30 15:50:29 2019 +0100 @@ -28,107 +28,98 @@ #include #include -#include +#include +#include #include -#include "RecfileWriter.h" - namespace relpipe { namespace out { namespace recfile { using namespace relpipe::reader; -class RecfileHandler : public handlers::RelationalReaderValueHadler { +class RecfileHandler : public handlers::RelationalReaderStringHadler { private: - shared_ptr recfileWriter; - std::vector columnTypes; - std::vector columnTypeCodes; - std::vector columnNames; + std::ostream& output; + wstring_convert> convertor; // XML output will be always in UTF-8 + std::vector attributeTypes; + std::vector attributeTypeCodes; + std::vector attributeNames; integer_t valueCount = 0; - integer_t columnCount = 0; + integer_t attributeCount = 0; integer_t relationCount = 0; + void writeRelationName(const string_t& name) { + // FIXME: escaping/filtering + output << "%rec: " << convertor.to_bytes(name) << std::endl; + } + + const std::string toRecfileType(const TypeId& type) { + switch (type) { + case TypeId::BOOLEAN: return "bool"; + case TypeId::INTEGER: return "int"; + case TypeId::STRING: return ""; // TODO: string type? + default: throw RelpipeReaderException(L"Unsupported type – unable to convert to a Recfile type"); + } + } + + void writeAttributeMetadata(const handlers::AttributeMetadata& attribute) { + // FIXME: escaping/filtering + // FIXME: translate to recfile types + output << "%type: " << convertor.to_bytes(attribute.getAttributeName()) << " " << toRecfileType(attribute.getTypeId()) << std::endl; + } + + void writeSeparator() { + output << std::endl; + } + + void writeAttribute(const string_t& name, const TypeId& type, const string_t& value) { + // FIXME: escaping/filtering + output << convertor.to_bytes(name) << ": "; + + for (char ch : convertor.to_bytes(value)) { + output << ch; + if (ch == '\n') output << "+ "; + } + + output << std::endl; + } + public: - RecfileHandler(std::ostream& output) : recfileWriter(new RecfileWriter(output)) { + RecfileHandler(std::ostream& output) : output(output) { } void startRelation(string_t name, std::vector attributes) override { valueCount = 0; - columnCount = 0; + attributeCount = 0; - if (relationCount == 0) { - recfileWriter->writeStartSequence(); // root - } else { - recfileWriter->writeEndSequence(); - recfileWriter->writeEndSequence(); - } + if (relationCount) writeSeparator(); + relationCount++; - recfileWriter->writeStartSequence(); // relation - - recfileWriter->writeString(name); - + writeRelationName(name); - recfileWriter->writeStartSequence(); // relation metadata - columnCount = attributes.size(); - columnTypes.resize(columnCount); - columnTypeCodes.resize(columnCount); - columnNames.resize(columnCount); + attributeCount = attributes.size(); + attributeTypes.resize(attributeCount); + attributeTypeCodes.resize(attributeCount); + attributeNames.resize(attributeCount); for (int i = 0; i < attributes.size(); i++) { - columnNames[i] = attributes[i].getAttributeName(); - columnTypes[i] = attributes[i].getTypeId(); - columnTypeCodes[i] = attributes[i].getTypeName(); - - recfileWriter->writeStartSequence(); // attribute-metadata - recfileWriter->writeString(columnNames[i]); - recfileWriter->writeString(columnTypeCodes[i]); - recfileWriter->writeEndSequence(); + attributeNames[i] = attributes[i].getAttributeName(); + attributeTypes[i] = attributes[i].getTypeId(); + attributeTypeCodes[i] = attributes[i].getTypeName(); + writeAttributeMetadata(attributes[i]); } - recfileWriter->writeEndSequence(); - } - void attribute(const void* value, const std::type_info& type) override { - integer_t i = valueCount % columnCount; - - if (i == 0 && valueCount) recfileWriter->writeEndSequence(); - if (i == 0) recfileWriter->writeStartSequence(); - + void attribute(const string_t& value) override { + integer_t i = valueCount % attributeCount; + if (i == 0) writeSeparator(); valueCount++; - - switch (columnTypes[i]) { - case TypeId::BOOLEAN: - { - assert(type == typeid (boolean_t)); - auto* typedValue = static_cast (value); - recfileWriter->writeBoolean(*typedValue); - break; - } - case TypeId::INTEGER: - { - assert(type == typeid (integer_t)); - auto* typedValue = static_cast (value); - recfileWriter->writeInteger(*typedValue); - break; - } - case TypeId::STRING: - { - assert(type == typeid (string_t)); - auto* typedValue = static_cast (value); - recfileWriter->writeString(*typedValue); - break; - } - default: - throw cli::RelpipeCLIException(L"Unsupported type in RecfileHandler.attribute()", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); - } - + writeAttribute(attributeNames[i], attributeTypes[i], value); } void endOfPipe() { - if (valueCount) recfileWriter->writeEndSequence(); - if (relationCount) recfileWriter->writeEndSequence(); - recfileWriter->writeEndSequence(); + if (valueCount) writeSeparator(); } };