read using std::function v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 03 Sep 2018 23:40:12 +0200
branchv_0
changeset 18 e11f1ad20826
parent 17 ec750c536705
child 19 3e1308e7606d
read using std::function
include/relpipe/reader/handlers/RelationalReaderStringHandler.h
src/DataTypeReader.h
src/DataTypeReaderBase.h
src/StreamRelationalReader.h
--- a/include/relpipe/reader/handlers/RelationalReaderStringHandler.h	Mon Aug 27 00:06:14 2018 +0200
+++ b/include/relpipe/reader/handlers/RelationalReaderStringHandler.h	Mon Sep 03 23:40:12 2018 +0200
@@ -13,6 +13,11 @@
 public:
 	
 	virtual void attribute(const string_t& value) = 0;
+	
+	// TODO: null values:
+	// a) special constant for null value
+	// b) virtual void attribute(const string_t& value, boolean_t isNull) = 0;
+	// c) virtual void null() = 0;
 
 };
 
--- a/src/DataTypeReader.h	Mon Aug 27 00:06:14 2018 +0200
+++ b/src/DataTypeReader.h	Mon Sep 03 23:40:12 2018 +0200
@@ -1,5 +1,8 @@
 #pragma once
 
+#include <sstream>
+#include <functional>
+
 #include "DataTypeReaderBase.h"
 
 namespace relpipe {
@@ -20,6 +23,16 @@
 		return toString(readValue(input));
 	}
 
+	virtual void read(std::istream &input, std::function<void(const void *, const std::type_info&) > handler) override {
+		T value = readValue(input);
+		handler(&value, typeid (T));
+	}
+
+	virtual void read(std::istream &input, std::function<void(const string_t&, const void *, const std::type_info&) > handler) override {
+		T value = readValue(input);
+		handler(toString(value), &value, typeid (T));
+	}
+
 	virtual string_t toString(const T& value) = 0;
 
 };
--- a/src/DataTypeReaderBase.h	Mon Aug 27 00:06:14 2018 +0200
+++ b/src/DataTypeReaderBase.h	Mon Sep 03 23:40:12 2018 +0200
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <string>
+#include <functional>
 #include "../include/relpipe/reader/TypeId.h"
 #include "../include/relpipe/reader/typedefs.h"
 
@@ -24,6 +25,8 @@
 	};
 
 	/**
+	 * TODO: delete, use handler?
+	 * 
 	 * @param input input stream, should be at position where the value is to be read; the stream will not be closed afred reading
 	 * @return read value in form of the string representation of given data type.
 	 * E.g. integer 123 is returned as a character string "123",
@@ -33,6 +36,22 @@
 	virtual string_t readString(std::istream &input) = 0;
 
 	/**
+	 * The value is read from the input and then passed to the handler.
+	 * 
+	 * @param input
+	 * @param handler
+	 */
+	virtual void read(std::istream &input, std::function<void(const void *, const std::type_info&) > handler) = 0;
+
+	/**
+	 * TODO: documentation
+	 * 
+	 * @param input
+	 * @param handler
+	 */
+	virtual void read(std::istream &input, std::function<void(const string_t&, const void *, const std::type_info&) > handler) = 0;
+
+	/**
 	 * @param dataType data type code as defined in DDP L0
 	 * @return whether this class supports conversions of this type
 	 */
--- a/src/StreamRelationalReader.h	Mon Aug 27 00:06:14 2018 +0200
+++ b/src/StreamRelationalReader.h	Mon Sep 03 23:40:12 2018 +0200
@@ -29,6 +29,7 @@
 	types::IntegerDataTypeReader integerReader;
 	types::StringDataTypeReader stringReader;
 	std::vector<DataTypeReaderBase*> readers = {&booleanReader, &integerReader, &stringReader};
+
 	std::vector<handlers::RelationalReaderStringHadler*> stringHandlers;
 	std::vector<handlers::RelationalReaderValueHadler*> valueHandlers;
 
@@ -45,6 +46,26 @@
 	 * types of columns in the current table
 	 */
 	std::vector<TypeId> columnTypes;
+	std::vector<string_t> columnNames;
+	std::vector<std::pair<string_t, TypeId>> columns;
+
+	/**
+	 * TODO: remove?
+	 */
+	string_t readString(std::istream &input, const TypeId typeId) {
+		for (DataTypeReaderBase* reader : readers) if (reader->supports(typeId)) return reader->readString(input);
+		throw RelpipeReaderException(L"Unsupported data type: " + (int) typeId);
+	}
+
+	void read(std::istream &input, std::function<void(const void *, const std::type_info&) > handler, const TypeId typeId) {
+		for (DataTypeReaderBase* reader : readers) if (reader->supports(typeId)) return reader->read(input, handler);
+		throw RelpipeReaderException(L"Unsupported data type: " + (int) typeId);
+	}
+
+	void read(std::istream &input, std::function<void(const string_t&, const void *, const std::type_info&) > handler, const TypeId typeId) {
+		for (DataTypeReaderBase* reader : readers) if (reader->supports(typeId)) return reader->read(input, handler);
+		throw RelpipeReaderException(L"Unsupported data type: " + (int) typeId);
+	}
 
 public:
 
@@ -66,29 +87,95 @@
 	}
 
 	void process() override {
-		for (int i = 0; i < stringHandlers.size(); i++) {
-			// FIXME: parse and call methods
-			stringHandlers[i]->startRelation(L"TODO: table",{
-				{L"a", TypeId::STRING},
-				{L"b", TypeId::STRING},
-				{L"c", TypeId::STRING}
-			});
+
+		while (true) {
+			integer_t dataPart;
+			try {
+				dataPart = integerReader.readValue(input);
+				// output << "dataPart: " << dataPart << endl;
+			} catch (RelpipeReaderException e) {
+				if (input.eof() && input.gcount() == 0) {
+					if (dataPart == DATA_PART_ROW) {
+						// last part was row
+						// input was fully read
+						// we are finished
+						// TODO: printCachedData(output); ???
+						return;
+					} else if (dataPart == DATA_PART_START) {
+						// Empty relation might be weird but it is valid data.
+						// Actually, it is not so weird as it looks.
+						// fwprintf(stderr, L"Warning: The table has no rows. Weird… but OK.\n");
+						return;
+					} else {
+						// in current format, there is no other data part
+						// so this will never happen
+						// but maybe later…
+						throw RelpipeReaderException(L"Unexpected EOF");
+					}
+				} else if (input.eof()) {
+					fwprintf(stderr, L"Error: found some unexpected data on the input stream: %d\n", input.gcount());
+					throw e;
+				} else {
+					// other error
+					throw e;
+				}
+			}
+
+			if (dataPart == DATA_PART_START) {
+				// Print data of previous table
+				// TODO: if (values.size() > 0) printCachedData(output); ???
+
+				// Read table name
+				string_t tableName = stringReader.readValue(input);
+
+				// Read column count
+				columnCount = integerReader.readValue(input);
+
+				columnTypes.resize(columnCount);
+				columnNames.resize(columnCount);
+				columns.resize(columnCount);
+
+				// Read column names
+				for (int i = 0; i < columnCount; i++) {
+					columnNames[i] = stringReader.readValue(input);
+				}
+
+				// Read column types
+				for (int i = 0; i < columnCount; i++) {
+					TypeId typeId = (TypeId) integerReader.readValue(input); // TODO: přetypování OK?
+					string_t typeCode = toTypeCode(typeId); // validate typeId TODO: je potřeba?
+					columnTypes[i] = typeId;
+				}
+
+				for (int i = 0; i < columnCount; i++) {
+					columns[i] = {columnNames[i], columnTypes[i]};
+				}
+
+				for (int i = 0; i < stringHandlers.size(); i++) stringHandlers[i]->startRelation(tableName, columns);
+				for (int i = 0; i < valueHandlers.size(); i++) valueHandlers[i]->startRelation(tableName, columns);
+
+			} else if (dataPart == DATA_PART_ROW) {
+				for (int i = 0; i < columnCount; i++) {
+					TypeId typeId = columnTypes[i];
+
+					if (stringHandlers.empty()) {
+						read(input, [&](const void * rawValue, const std::type_info & typeInfo) {
+							for (int i = 0; i < valueHandlers.size(); i++) valueHandlers[i]->attribute(rawValue, typeInfo);
+						}, typeId);
+					} else {
+						read(input, [&](const string_t& stringValue, const void * rawValue, const std::type_info & typeInfo) {
+							for (int i = 0; i < stringHandlers.size(); i++) stringHandlers[i]->attribute(stringValue);
+							for (int i = 0; i < valueHandlers.size(); i++) valueHandlers[i]->attribute(rawValue, typeInfo);
+						}, typeId);
+					}
+				}
+
+			} else {
+				throw RelpipeReaderException(L"Unknown data part");
+			}
 		}
 
-		for (int i = 0; i < valueHandlers.size(); i++) {
-			// FIXME: parse and call methods
-			valueHandlers[i]->startRelation(L"TODO: table value",{
-				{L"av", TypeId::STRING},
-				{L"bv", TypeId::STRING},
-				{L"cv", TypeId::STRING}
-			});
-		}
-
-		// FIXME: parse and call methods
-		for (int row = 0; row < 3; row++) {
-			for (int i = 0; i < stringHandlers.size(); i++) stringHandlers[i]->attribute(L"x");
-
-		}
+		throw RelpipeReaderException(L"Unexpected exception"); // should never happen
 
 	}