From 4c67ae418c622d78c3a77b19beadbfe3cc7d7a06 Mon Sep 17 00:00:00 2001
From: rinkk <karsten.rink@ufz.de>
Date: Thu, 28 Jul 2016 11:35:34 +0200
Subject: [PATCH] added write functionality for csv

---
 Applications/FileIO/CsvInterface.cpp | 67 ++++++++++++++++++++++++++++
 Applications/FileIO/CsvInterface.h   | 45 ++++++++++++++++++-
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/Applications/FileIO/CsvInterface.cpp b/Applications/FileIO/CsvInterface.cpp
index ce2878960cf..6163f99796f 100644
--- a/Applications/FileIO/CsvInterface.cpp
+++ b/Applications/FileIO/CsvInterface.cpp
@@ -14,6 +14,8 @@
 #include "CsvInterface.h"
 
 #include <algorithm>
+#include <iostream>
+#include <numeric>
 #include <stdexcept>
 
 #include "GeoLib/Point.h"
@@ -181,4 +183,69 @@ std::size_t CsvInterface::findColumn(std::string const& line, char delim, std::s
     return count;
 }
 
+void CsvInterface::addIndexVectorForWriting(std::size_t s)
+{
+    std::vector<int> idx_vec(s);
+    std::iota(idx_vec.begin(), idx_vec.end(), 0);
+    addVectorForWriting("Index", idx_vec);
+}
+
+bool CsvInterface::write()
+{
+    if (_data.empty())
+    {
+        ERR ("CsvInterface::write() - No data to write.");
+        return false;
+    }
+
+    std::size_t const vec_size (getVectorSize(0));
+    std::size_t const n_vecs (_data.size());
+    for (std::size_t i=1; i<n_vecs; ++i)
+    {
+        if (getVectorSize(i) != vec_size)
+        {
+            ERR ("CsvInterface::write() - Data vectors are not equally long.");
+            return false;
+        }
+    }
+
+    _out << _vec_names[0];
+    for (std::size_t i=1; i<n_vecs; ++i)
+        _out << "\t " << _vec_names[i];
+    _out << std::endl;
+
+    for (std::size_t j=1; j<vec_size; ++j)
+    {
+        writeValue(0,j);
+        for (std::size_t i=1; i<n_vecs; ++i)
+        {
+            _out << "\t ";
+            writeValue(i,j);
+        }
+        _out << std::endl;
+    }
+    return true;
+}
+
+std::size_t CsvInterface::getVectorSize(std::size_t idx) const
+{
+    if (_data[idx].type() == typeid(std::vector<std::string>))
+        return boost::any_cast<std::vector<std::string>>(_data[idx]).size();
+    else if (_data[idx].type() == typeid(std::vector<double>))
+        return boost::any_cast<std::vector<double>>(_data[idx]).size();
+    else if (_data[idx].type() == typeid(std::vector<int>))
+        return boost::any_cast<std::vector<int>>(_data[idx]).size();
+    return 0;
+}
+
+void CsvInterface::writeValue(std::size_t vec_idx, std::size_t in_vec_idx)
+{
+    if (_data[vec_idx].type() == typeid(std::vector<std::string>))
+        _out << boost::any_cast<std::vector<std::string>>(_data[vec_idx])[in_vec_idx];
+    else if (_data[vec_idx].type() == typeid(std::vector<double>))
+        _out << boost::any_cast<std::vector<double>>(_data[vec_idx])[in_vec_idx];
+    else if (_data[vec_idx].type() == typeid(std::vector<int>))
+        _out << boost::any_cast<std::vector<int>>(_data[vec_idx])[in_vec_idx];
+}
+
 } // end namespace FileIO
diff --git a/Applications/FileIO/CsvInterface.h b/Applications/FileIO/CsvInterface.h
index e78597c96e5..a6653f888d3 100644
--- a/Applications/FileIO/CsvInterface.h
+++ b/Applications/FileIO/CsvInterface.h
@@ -15,6 +15,7 @@
 #define CSVINTERFACE_H_
 
 #include <logog/include/logog.hpp>
+#include <boost/any.hpp>
 
 #include <array>
 #include <fstream>
@@ -22,10 +23,12 @@
 #include <limits>
 #include <list>
 #include <string>
+#include <typeinfo>
 #include <vector>
 
 
 #include "BaseLib/StringTools.h"
+#include "BaseLib/IO/Writer.h"
 
 namespace GeoLib {
     class Point;
@@ -36,9 +39,36 @@ namespace FileIO {
 /**
  * Interface for reading CSV file formats.
  */
-class CsvInterface {
+class CsvInterface  : public BaseLib::IO::Writer
+{
 
 public:
+    /// Contructor (only needed for writing files)
+    CsvInterface() {};
+
+    /// Adds an index vector of size s to the CSV file
+    void addIndexVectorForWriting(std::size_t s);
+
+    /// Adds a data vector to the CSV file. All data vectors have to have the same size.
+    /// Vectors will be written in the same sequence they have been added to the interfaceW.
+    template<typename T>
+    bool addVectorForWriting(std::string const& vec_name, std::vector<T> const& vec)
+    {
+        if (typeid(vec) == typeid(std::vector<std::string>) ||
+            typeid(vec) == typeid(std::vector<double>) ||
+            typeid(vec) == typeid(std::vector<int>))
+        {
+            _vec_names.push_back(vec_name);
+            _data.push_back(vec);
+            return true;
+        }
+        ERR ("Vector type currently not supported.");
+        return false;
+    }
+
+    /// Writes the CSV file.
+    bool write();
+
     /**
      * Reads 3D points from a CSV file. It is assumed that the file has a header
      * specifying a name for each of the columns. The first three columns will be
@@ -178,6 +208,19 @@ private:
 
     /// Returns the number of the column with column_name (or std::numeric_limits::max() if no such column has been found).
     static std::size_t findColumn(std::string const& line, char delim, std::string const& column_name);
+
+    /// Returns the size of the vector with the given index
+    std::size_t getVectorSize(std::size_t idx) const;
+
+    /**
+     * Writes a value from a vector to the file.
+     * \param vec_idx     Index of the vector
+     * \param in_vec_idx  Entry in the selected vector
+     */
+    void writeValue(std::size_t vec_idx, std::size_t in_vec_idx);
+
+    std::vector<std::string> _vec_names;
+    std::vector< boost::any > _data;
 };
 
 } // FileIO
-- 
GitLab