# HG changeset patch # User František Kučera # Date 1553957429 -3600 # Node ID 1b4ca23e5d043e867a8f1551ee3e8af94b001864 # Parent 9005fdd81bcabd81411cd58ad9f827f7447d4cf6 draft version so one can do: relpipe-in-fstab | relpipe-out-recfile | recsel -e 'type="btrfs"' | rec2csv | relpipe-in-csv | relpipe-out-asn1 | dumpasn1 - 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(); } }; diff -r 9005fdd81bca -r 1b4ca23e5d04 src/RecfileWriter.h --- a/src/RecfileWriter.h Sat Mar 30 01:12:42 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/** - * Relational pipes - * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; - -namespace relpipe { -namespace out { -namespace recfile { - -using namespace relpipe::reader; - -/** - * A simple library for writing ASN.1 BER encoded files. - */ -class RecfileWriter { -private: - ostream& output; - wstring_convert> convertor; // only UTF8String is supported - int sequenceLevel = 0; - - void xxx_indent() { - // FIXME: remove - for (int i = 0; i < sequenceLevel; i++) output << " "; - } - -public: - - RecfileWriter(std::ostream& output) : output(output) { - } - - virtual ~RecfileWriter() { - if (sequenceLevel) output << "Unable to close RecfileWriter because there are not ended sequences." << endl; // FIXME: better error handling - output.flush(); - } - - void writeStartSequence() { - xxx_indent(); - output << "sequence start" << endl; - - sequenceLevel++; - } - - void writeEndSequence() { - if (sequenceLevel == 0) throw cli::RelpipeCLIException(L"Unable to writeEndSequence() if not sequence is currently started.", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // should not happen, error in the program - - sequenceLevel--; - - xxx_indent(); - output << "sequence end" << endl; - } - - void writeBoolean(const boolean_t& value) { - xxx_indent(); - output << "boolean" << (value ? "true" : "false") << endl; - } - - void writeInteger(const integer_t& value) { - xxx_indent(); - output << "integer: " << value << endl; - } - - void writeString(const string_t& value) { - xxx_indent(); - output << "string: " << convertor.to_bytes(value) << endl; - } - -}; - -} -} -} \ No newline at end of file