# HG changeset patch # User František Kučera # Date 1544183379 -3600 # Node ID 2f3c9e508827d739c25c9fea18fef1d6e1ac9cce project skeleton: cmake, netbeans, code from relpipe-out-xml diff -r 000000000000 -r 2f3c9e508827 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,13 @@ +syntax: glob + +*~ +CMakeLists.txt.user + +syntax: regexp + +^temp/ + +^\.dep\.inc +^dist/ +^build/ +^nbproject/private/ diff -r 000000000000 -r 2f3c9e508827 CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,19 @@ +# Relational pipes +# Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +project (relpipeout-ods.cpp) +cmake_minimum_required(VERSION 2.8) +add_subdirectory (src) diff -r 000000000000 -r 2f3c9e508827 nbproject/configurations.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nbproject/configurations.xml Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,135 @@ + + + + + + + relpipe-out-ods.cpp + + + + CMakeLists.txt + build/Debug/Makefile + build/Release/Makefile + + + ^(nbproject|build)$ + + . + + build/Debug/Makefile + + + + default + false + false + + + + + + + + + build/Debug + ${MAKE} -f Makefile + ${MAKE} -f Makefile clean + build/Debug/src/relpipe-out-ods + + + ../relpipe-lib-cli.cpp/include/relpipe/cli + ../relpipe-lib-reader.cpp/include/relpipe/reader + src + ../relpipe-lib-reader.cpp/include/relpipe/reader/handlers + ../relpipe-lib-cli.cpp/include + ../relpipe-lib-reader.cpp/include + build/Debug/src + + + + + build/Debug + ${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../.. + true + + + + + + + + + + default + false + false + + + + + + build/Release + ${MAKE} -f Makefile + ${MAKE} -f Makefile clean + build/Release/src/welcome + + + src + + + NDEBUG + + + + + build/Release + ${CMAKE} -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${IDE_CC} -DCMAKE_CXX_COMPILER=${IDE_CXX} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ../.. + true + + + + + diff -r 000000000000 -r 2f3c9e508827 nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nbproject/project.xml Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,72 @@ + + + + org.netbeans.modules.cnd.makeproject + + + relpipe-out-ods.cpp + + cpp + h + UTF-8 + + . + + + + . + + + + Debug + 0 + + + Release + 0 + + + + false + + + + diff -r 000000000000 -r 2f3c9e508827 src/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/CMakeLists.txt Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,38 @@ +# Relational pipes +# Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(EXECUTABLE_FILE "relpipe-out-ods") + +# Relpipe libraries: +INCLUDE(FindPkgConfig) +pkg_check_modules (RELPIPE_LIBS relpipe-lib-reader.cpp relpipe-lib-cli.cpp) +include_directories(${RELPIPE_LIBS_INCLUDE_DIRS}) +link_directories(${RELPIPE_LIBS_LIBRARY_DIRS}) + +# Add ASan AddressSanitizer +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") +set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") +# From ASan wiki: "To get nicer stack traces in error messages add -fno-omit-frame-pointer." + +# Executable output: +add_executable( + ${EXECUTABLE_FILE} + OdsHandler.h + relpipe-out-ods.cpp +) + +# Link libraries: +target_link_libraries(${EXECUTABLE_FILE} ${RELPIPE_LIBS_LIBRARIES}) diff -r 000000000000 -r 2f3c9e508827 src/OdsHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/OdsHandler.h Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,139 @@ +/** + * Relational pipes + * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace relpipe { +namespace out { +namespace ods { + +using namespace relpipe::reader; + +class OdsHandler : public handlers::RelationalReaderStringHadler { +private: + std::wstring_convert> convertor; // XML output will be always in UTF-8 + const char* INDENT = "\t"; + + std::ostream &output; + + std::vector columnTypes; + std::vector columnTypeCodes; + std::vector columnNames; + integer_t valueCount = 0; + integer_t columnCount = 0; + integer_t relationCount = 0; + + const std::string escapeXmlText(const string_t &value) { + std::wstringstream result; + + for (auto & ch : value) { + switch (ch) { + case L'&': result << L"&"; + break; + case L'<': result << L"<"; + break; + case L'>': result << L">"; + break; + case L'\'': result << L"'"; // TODO: escape ' and " only in attributes + break; + case L'"': result << L"""; // TODO: escape ' and " only in attributes + break; + default: result << ch; + } + } + + return convertor.to_bytes(result.str()); + } + +public: + + OdsHandler(std::ostream& output) : output(output) { + } + + void startRelation(string_t name, std::vector attributes) override { + // TODO: refactor and move common XML functions to relpipe-lib-xml + + valueCount = 0; + columnCount = 0; + + if (relationCount == 0) { + output << "" << std::endl; + output << "" << std::endl; + // TODO: xmlns + } else { + output << INDENT << INDENT << "" << std::endl; + output << INDENT << "" << std::endl; + } + relationCount++; + output << INDENT << "" << std::endl; + + output << INDENT << INDENT << "" << escapeXmlText(name) << "" << std::endl; + + + columnCount = attributes.size(); + columnTypes.resize(columnCount); + columnTypeCodes.resize(columnCount); + columnNames.resize(columnCount); + for (int i = 0; i < attributes.size(); i++) { + columnNames[i] = attributes[i].getAttributeName(); + columnTypes[i] = attributes[i].getTypeId(); + columnTypeCodes[i] = attributes[i].getTypeName(); + } + + // TODO: print attribute metadata + } + + void attribute(const string_t& value) override { + integer_t i = valueCount % columnCount; + + if (i == 0 && valueCount) output << INDENT << INDENT << "" << std::endl; + if (i == 0) output << INDENT << INDENT << "" << std::endl; + + valueCount++; + + // TODO: print attribute metadata (optional) + output << INDENT << INDENT << INDENT << ""; + output << escapeXmlText(value); + output << "" << std::endl; + + } + + void endOfPipe() { + if (valueCount) output << INDENT << INDENT << "" << std::endl; + if (relationCount) output << INDENT << "" << std::endl; + output << "" << std::endl; + + } + +}; + +} +} +} diff -r 000000000000 -r 2f3c9e508827 src/relpipe-out-ods.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/relpipe-out-ods.cpp Fri Dec 07 12:49:39 2018 +0100 @@ -0,0 +1,63 @@ +/** + * Relational pipes + * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "OdsHandler.h" + +using namespace relpipe::cli; +using namespace relpipe::reader; +using namespace relpipe::out::ods; + +int main(int argc, char** argv) { + setlocale(LC_ALL, ""); + CLI::untieStdIO(); + CLI cli(argc, argv); + + int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; + + try { + + // TODO: color syntax highlighting if stdout is TTY: + // if (isatty(fileno(stdout))) std::cout << "color" << std::endl; + // else std::cout << "no-color" << std::endl; + + std::shared_ptr reader(Factory::create(std::cin)); + OdsHandler handler(std::cout); + reader->addHandler(&handler); + reader->process(); + resultCode = CLI::EXIT_CODE_SUCCESS; + } catch (RelpipeCLIException e) { + fwprintf(stderr, L"Caught CLI exception: %ls\n", e.getMessge().c_str()); + fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount()); + resultCode = e.getExitCode(); + } catch (RelpipeReaderException e) { + fwprintf(stderr, L"Caught Reader exception: %ls\n", e.getMessge().c_str()); + fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount()); + resultCode = CLI::EXIT_CODE_DATA_ERROR; + } + + return resultCode; +}