# HG changeset patch # User František Kučera # Date 1547071491 -3600 # Node ID 5eb4d149c6e25065b3a0291b2954af5fbc354001 # Parent eca0b23802e80689f6e924efb34d39bf8a81f8b4 first working version diff -r eca0b23802e8 -r 5eb4d149c6e2 src/relpipe-in-csv.cpp --- a/src/relpipe-in-csv.cpp Wed Jan 09 17:23:02 2019 +0100 +++ b/src/relpipe-in-csv.cpp Wed Jan 09 23:04:51 2019 +0100 @@ -16,7 +16,7 @@ * along with this program. If not, see . */ #include -#include +#include #include #include #include @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -33,13 +34,79 @@ using namespace relpipe::cli; using namespace relpipe::writer; -/** - * see https://hg.frantovo.cz/sql-api/file/tip/prototyp/prototyp.sql#l49 - */ -void processDataStream(ostream &output, istream* input) { +bool readValue(istream& input, stringstream& currentValue, bool& lastInRecord) { + lastInRecord = false; + char ch; + input.get(ch); + if (ch == '"') { + while (input.get(ch)) { + if (ch == '"') { + input.get(ch); + if (ch == '"') { + currentValue << ch; + } else { + if (ch == '\r') input.get(ch); + if (ch == '\n') lastInRecord = true; + else if (ch != ',') throw RelpipeWriterException(L"Unexpected character (should be „\\n“ or „,“)"); + return true; + } + } else { + currentValue << ch; + } + } + } else if (ch == ',') { + return true; + } else if (ch == '\n') { + lastInRecord = true; + return true; + } else if (ch == '\r') { + currentValue << ch; + if (ch == '\n') { + lastInRecord = true; + return true; + } else { + throw RelpipeWriterException(L"Crazy carriage stuck during journey"); + } + } else { + for (currentValue << ch; input.get(ch);) { + switch (ch) { + case ',': return true; + case '\r': break; + case '\n': + lastInRecord = true; + return true; + default: currentValue << ch; + } + } + } + return false; +} - for (char ch; input->get(ch);) { - output << "ch: " << ch << endl; +void processDataStream(ostream &output, istream& input) { + wstring_convert < codecvt_utf8> convertor; // UTF-8 is required for CSV + std::shared_ptr writer(Factory::create(output)); + vector metadata; + bool headerDone = false; + bool lastInRecord = false; + stringstream currentValue; + + + while (readValue(input, currentValue, lastInRecord) && input.good()) { + if (headerDone) { + writer->writeAttribute(convertor.from_bytes(currentValue.str())); + } else { + AttributeMetadata am; + am.attributeName = convertor.from_bytes(currentValue.str()); + am.typeId = TypeId::STRING; // TODO: support also other types passed as CLI parameters + metadata.push_back(am); + if (lastInRecord) { + headerDone = true; + writer->startRelation(L"csv", metadata, true); // TODO: support also custom relation name passed as CLI parameter + } + } + + currentValue.str(""); + currentValue.clear(); } } @@ -51,7 +118,7 @@ int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; try { - processDataStream(cout, &cin); + processDataStream(cout, cin); resultCode = CLI::EXIT_CODE_SUCCESS; } catch (RelpipeWriterException e) { fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());