# HG changeset patch # User František Kučera # Date 1536010812 -7200 # Node ID e11f1ad208269a375eccbd4412d954c84c1ac121 # Parent ec750c536705e906c84dfb151af4b36d1ce749af read using std::function diff -r ec750c536705 -r e11f1ad20826 include/relpipe/reader/handlers/RelationalReaderStringHandler.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; }; diff -r ec750c536705 -r e11f1ad20826 src/DataTypeReader.h --- 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 +#include + #include "DataTypeReaderBase.h" namespace relpipe { @@ -20,6 +23,16 @@ return toString(readValue(input)); } + virtual void read(std::istream &input, std::function handler) override { + T value = readValue(input); + handler(&value, typeid (T)); + } + + virtual void read(std::istream &input, std::function handler) override { + T value = readValue(input); + handler(toString(value), &value, typeid (T)); + } + virtual string_t toString(const T& value) = 0; }; diff -r ec750c536705 -r e11f1ad20826 src/DataTypeReaderBase.h --- 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 +#include #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 handler) = 0; + + /** + * TODO: documentation + * + * @param input + * @param handler + */ + virtual void read(std::istream &input, std::function handler) = 0; + + /** * @param dataType data type code as defined in DDP L0 * @return whether this class supports conversions of this type */ diff -r ec750c536705 -r e11f1ad20826 src/StreamRelationalReader.h --- 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 readers = {&booleanReader, &integerReader, &stringReader}; + std::vector stringHandlers; std::vector valueHandlers; @@ -45,6 +46,26 @@ * types of columns in the current table */ std::vector columnTypes; + std::vector columnNames; + std::vector> 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 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 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 }