draft version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 30 Mar 2019 15:50:29 +0100
branchv_0
changeset 1 1b4ca23e5d04
parent 0 9005fdd81bca
child 2 db029ce62ec5
draft version so one can do: relpipe-in-fstab | relpipe-out-recfile | recsel -e 'type="btrfs"' | rec2csv | relpipe-in-csv | relpipe-out-asn1 | dumpasn1 -
src/RecfileHandler.h
src/RecfileWriter.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 <relpipe/reader/typedefs.h>
 #include <relpipe/reader/TypeId.h>
-#include <relpipe/reader/handlers/RelationalReaderValueHandler.h>
+#include <relpipe/reader/RelpipeReaderException.h>
+#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
 #include <relpipe/reader/handlers/AttributeMetadata.h>
 
-#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> recfileWriter;
-	std::vector<TypeId> columnTypes;
-	std::vector<string_t> columnTypeCodes;
-	std::vector<string_t> columnNames;
+	std::ostream& output;
+	wstring_convert<codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
+	std::vector<TypeId> attributeTypes;
+	std::vector<string_t> attributeTypeCodes;
+	std::vector<string_t> 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<handlers::AttributeMetadata> 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<const boolean_t*> (value);
-				recfileWriter->writeBoolean(*typedValue);
-				break;
-			}
-			case TypeId::INTEGER:
-			{
-				assert(type == typeid (integer_t));
-				auto* typedValue = static_cast<const integer_t*> (value);
-				recfileWriter->writeInteger(*typedValue);
-				break;
-			}
-			case TypeId::STRING:
-			{
-				assert(type == typeid (string_t));
-				auto* typedValue = static_cast<const string_t*> (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();
 	}
 
 };
--- 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 <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-#include <codecvt>
-#include <locale>
-
-#include <relpipe/reader/typedefs.h>
-#include <relpipe/cli/RelpipeCLIException.h>
-
-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<codecvt_utf8<wchar_t>> 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