--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/StdInCommand.h Sat Jul 28 22:29:40 2018 +0200
@@ -0,0 +1,89 @@
+#pragma once
+
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <string>
+
+#include <typedefs.h>
+#include <locale>
+
+#include "Command.h"
+#include "CLI.h"
+#include "RelpipeCLIException.h"
+
+namespace relpipe {
+namespace in {
+namespace cli {
+
+/**
+ * TODO: consider code merge with ArgumentsCommand
+ */
+class StdInCommand : public Command {
+private:
+ wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+
+ /**
+ * Reads next value from arguments and (if no arguments left) from input
+ * @param input
+ * @param arguments
+ * @param i current index in the arguments vector
+ * @param required if true, exception is thrown when no data found
+ * @return
+ */
+ relpipe::writer::string_t readNext(std::istream& input, const std::vector<relpipe::writer::string_t>& arguments, size_t& i, relpipe::writer::boolean_t required) {
+ using namespace relpipe::writer;
+ using namespace relpipe::cli;
+
+ if (i < arguments.size()) {
+ return arguments[i++];
+ } else {
+ std::stringstream value;
+
+ while (true) {
+ char ch;
+ input.get(ch);
+ if (ch == 0 || input.eof() || input.fail()) break;
+ else value << ch;
+ }
+
+ return convertor.from_bytes(value.str());
+ }
+ }
+
+
+public:
+
+ void process(std::istream& input, std::ostream& output, const relpipe::writer::string_t& command, const std::vector<relpipe::writer::string_t>& arguments) override {
+ using namespace relpipe::writer;
+
+ size_t i = 0;
+ string_t relationName = readNext(input, arguments, i, true);
+ integer_t attributeCount = std::stoul(readNext(input, arguments, i, true)); // TODO: use integer data type's method?
+ boolean_t writeHeader = true; // TODO: add option for header omitting
+
+ std::shared_ptr<RelationalWriter> writer(Factory::create(output));
+
+ std::vector<std::pair<string_t, TypeId >> attributes(attributeCount);
+
+ for (size_t j = 0; j < attributeCount; j++) {
+ string_t attributeName = readNext(input, arguments, i, true);
+ TypeId attributeType = writer->toTypeId(readNext(input, arguments, i, true));
+ attributes[j] = {attributeName, attributeType};
+ }
+
+ writer->startRelation(relationName, attributes, writeHeader);
+
+ while (true) {
+ string_t value = readNext(input, arguments, i, false);
+ if (value.empty() && (input.eof() || input.fail())) break;
+ else writer->writeAttribute(value);
+ }
+ }
+};
+
+}
+}
+}
--- a/nbproject/configurations.xml Sat Jul 28 15:42:42 2018 +0200
+++ b/nbproject/configurations.xml Sat Jul 28 22:29:40 2018 +0200
@@ -9,6 +9,7 @@
<itemPath>Command.h</itemPath>
<itemPath>DemoCommand.h</itemPath>
<itemPath>RelpipeCLIException.h</itemPath>
+ <itemPath>StdInCommand.h</itemPath>
</logicalFolder>
<logicalFolder name="ResourceFiles"
displayName="Resource Files"
@@ -66,6 +67,8 @@
</item>
<item path="RelpipeCLIException.h" ex="false" tool="3" flavor2="0">
</item>
+ <item path="StdInCommand.h" ex="false" tool="3" flavor2="0">
+ </item>
<item path="relpipe-in-cli.cpp" ex="false" tool="1" flavor2="0">
</item>
</conf>
@@ -105,6 +108,8 @@
</item>
<item path="RelpipeCLIException.h" ex="false" tool="3" flavor2="0">
</item>
+ <item path="StdInCommand.h" ex="false" tool="3" flavor2="0">
+ </item>
<item path="relpipe-in-cli.cpp" ex="false" tool="1" flavor2="0">
</item>
</conf>
--- a/relpipe-in-cli.cpp Sat Jul 28 15:42:42 2018 +0200
+++ b/relpipe-in-cli.cpp Sat Jul 28 22:29:40 2018 +0200
@@ -11,14 +11,18 @@
#include "Command.h"
#include "ArgumentsCommand.h"
#include "DemoCommand.h"
+#include "StdInCommand.h"
using namespace relpipe::cli;
using namespace relpipe::in::cli;
using namespace relpipe::writer;
Command* findCommand(string_t commandName) {
+ // TODO: better command names
+ // TODO: help command
if (commandName == L"demo") return new DemoCommand();
else if (commandName == L"generate") return new ArgumentsCommand();
+ else if (commandName == L"generate-from-stdin") return new StdInCommand();
else throw RelpipeCLIException(L"Unknown command: " + commandName, CLI::EXIT_CODE_UNKNOWN_COMMAND);
}