writeAttribute() with raw pointer and type_info v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 22 Jul 2018 17:19:25 +0200
branchv_0
changeset 16 3613617d3076
parent 15 8fd6c4d44071
child 17 f2cccaa9dd38
writeAttribute() with raw pointer and type_info
include/RelationalWriter.h
src/DataTypeWriter.h
src/DataTypeWriterBase.h
src/StreamRelationalWriter.h
--- a/include/RelationalWriter.h	Sun Jul 22 10:26:22 2018 +0200
+++ b/include/RelationalWriter.h	Sun Jul 22 17:19:25 2018 +0200
@@ -22,6 +22,12 @@
 	virtual void startRelation(string_t name, std::vector<std::pair<string_t, TypeId>> attributes, boolean_t writeHeader) = 0;
 
 	virtual void writeRecord(std::vector<string_t> attributes) = 0;
+	
+	// TODO: write bitmap + attribute:
+	// virtual void writeBitmap(...) = 0;
+	// virtual void writeAttribute(string_t attribute) = 0;
+	
+	virtual void writeAttribute(const void* value, const std::type_info& type) = 0;
 
 };
 
--- a/src/DataTypeWriter.h	Sun Jul 22 10:26:22 2018 +0200
+++ b/src/DataTypeWriter.h	Sun Jul 22 17:19:25 2018 +0200
@@ -1,5 +1,8 @@
 #pragma once
 
+#include <functional>
+#include <sstream>
+
 #include "DataTypeWriterBase.h"
 
 namespace relpipe {
@@ -16,6 +19,17 @@
 
 	virtual void writeValue(std::ostream& output, const T& value) = 0;
 
+	void writeRaw(std::ostream& output, const void * value, const std::type_info& type) override {
+		if (type == typeid (T)) {
+			const T v = *(static_cast<const T*>(value));
+			writeValue(output, v);
+		} else {
+			wstringstream message;
+			message << L"Data type in writeRaw() does not match – got: " << type.name() << " but expected: " << typeid (T).name();
+			throw RelpipeWriterException(message.str());
+		}
+	}
+
 	void writeString(std::ostream& output, const string_t &stringValue) override {
 		writeValue(output, toValue(stringValue));
 	}
--- a/src/DataTypeWriterBase.h	Sun Jul 22 10:26:22 2018 +0200
+++ b/src/DataTypeWriterBase.h	Sun Jul 22 17:19:25 2018 +0200
@@ -32,6 +32,15 @@
 	virtual void writeString(std::ostream& output, const string_t &stringValue) = 0;
 
 	/**
+	 * @param output output stream, should be at position where the value is to be written; the stream will not be closed not flushed after writing
+	 * @param value raw pointer to the value, must exactly match data type of this writer
+	 * @param type used as a safety mechanism to avoid wrong pointer interpretation;
+	 * should be called in this way: writeRaw(output, valuePointer, typeid(valuePointer));
+	 * if the type does not match, the RelpipeWriterException is thrown
+	 */
+	virtual void writeRaw(std::ostream& output, const void * value, const std::type_info& type) = 0;
+
+	/**
 	 * @param dataType data type code as defined in DDP L0
 	 * @return whether this class supports conversions of this type
 	 */
--- a/src/StreamRelationalWriter.h	Sun Jul 22 10:26:22 2018 +0200
+++ b/src/StreamRelationalWriter.h	Sun Jul 22 17:19:25 2018 +0200
@@ -28,6 +28,10 @@
 	 * count of columns in the current table
 	 */
 	integer_t columnCount;
+	/**
+	 * number of column (0 = first) that will be written; after writing, the number is increased and prepared for next one
+	 */
+	integer_t currentColumn;
 
 	/**
 	 * types of columns in the current table
@@ -36,7 +40,12 @@
 
 	void writeString(const string_t &stringValue, const TypeId typeId) {
 		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeId)) return writer->writeString(output, stringValue);
-		throw RelpipeWriterException(L"Unsupported data type: " + static_cast<integer_t>(typeId));
+		throw RelpipeWriterException(L"Unsupported data type: " + static_cast<integer_t> (typeId));
+	}
+
+	void writeRaw(const void* value, const type_info& typeInfo, const TypeId typeId) {
+		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeId)) return writer->writeRaw(output, value, typeInfo);
+		throw RelpipeWriterException(L"Unsupported data type: " + static_cast<integer_t> (typeId));
 	}
 
 public:
@@ -52,12 +61,13 @@
 
 	string_t toTypeCode(const TypeId typeId) override {
 		for (DataTypeWriterBase* writer : writers) if (writer->supports(typeId)) return writer->getTypeCode();
-		throw RelpipeWriterException(L"Unsupported data type: " + static_cast<integer_t>(typeId));
+		throw RelpipeWriterException(L"Unsupported data type: " + static_cast<integer_t> (typeId));
 	}
-	
+
 	void startRelation(string_t name, std::vector<std::pair<string_t, TypeId> > attributes, boolean_t writeHeader) override {
 		string_t tableName = name;
 		columnCount = attributes.size();
+		currentColumn = 0;
 
 		// Write table name and column count:
 		integerWriter.writeValue(output, DATA_PART_START);
@@ -76,7 +86,7 @@
 		// Write column types:
 		for (size_t c = 0; c < columnCount; c++) {
 			TypeId typeId = attributes[c].second;
-			integerWriter.writeValue(output, static_cast<integer_t>(typeId));
+			integerWriter.writeValue(output, static_cast<integer_t> (typeId));
 			columnTypes[c] = typeId;
 		}
 
@@ -84,8 +94,9 @@
 
 	void writeRecord(std::vector<string_t> attributes) override {
 		// FIXME: check vector size
+		// FIXME: check currentColumn == 0
 		for (size_t c = 0; c < columnCount; c++) {
-			// TODO: support multiple rows in a single method call?
+			// TODO: do not support multiple rows in a single method call
 			if (c % columnCount == 0) {
 				integerWriter.writeValue(output, DATA_PART_ROW);
 			}
@@ -96,6 +107,12 @@
 		}
 	}
 
+	void writeAttribute(const void* value, const std::type_info& type) override {
+		if (currentColumn == 0) integerWriter.writeValue(output, DATA_PART_ROW);
+		writeRaw(value, type, columnTypes[currentColumn]);
+		if (++currentColumn == columnCount) currentColumn = 0;
+	}
+
 };
 
 }