From c93535842dd6abf3d1f1d15c7414d7934a593b49 Mon Sep 17 00:00:00 2001
From: rinkk <karsten.rink@ufz.de>
Date: Fri, 29 Mar 2019 14:41:46 +0100
Subject: [PATCH] Added method to return column-names to CSV interface

---
 Applications/FileIO/CsvInterface.cpp | 33 ++++++++++++++++++++++++++++
 Applications/FileIO/CsvInterface.h   |  5 +++++
 Tests/FileIO/TestCsvReader.cpp       |  9 ++++++--
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/Applications/FileIO/CsvInterface.cpp b/Applications/FileIO/CsvInterface.cpp
index b508181b095..f5850fb3103 100644
--- a/Applications/FileIO/CsvInterface.cpp
+++ b/Applications/FileIO/CsvInterface.cpp
@@ -22,6 +22,39 @@
 namespace FileIO {
 CsvInterface::CsvInterface() = default;
 
+std::vector<std::string> CsvInterface::getColumnNames(std::string const& fname,
+                                                      char const delim)
+{
+    std::ifstream in(fname.c_str());
+
+    if (!in.is_open())
+    {
+        ERR("CsvInterface::readPoints(): Could not open file %s.",
+            fname.c_str());
+        return std::vector<std::string>();
+    }
+    std::string line;
+    if (!getline(in, line))
+        return {};
+
+    std::list<std::string> fields;
+    if (delim != '\n')
+        fields = BaseLib::splitString(line, delim);
+
+    if (fields.size() < 2)
+    {
+        for (char const d : {'\t', ';', ','})
+        {
+            fields = BaseLib::splitString(line, d);
+            if (fields.size() > 1)
+            {
+                break;
+            }
+        }
+    }
+    return {begin(fields), end(fields)};
+}
+
 int CsvInterface::readPoints(std::string const& fname, char delim,
                              std::vector<GeoLib::Point*> &points)
 {
diff --git a/Applications/FileIO/CsvInterface.h b/Applications/FileIO/CsvInterface.h
index b2e0bdd6241..779d7de4a60 100644
--- a/Applications/FileIO/CsvInterface.h
+++ b/Applications/FileIO/CsvInterface.h
@@ -48,6 +48,11 @@ public:
     /// Returns the number of vectors currently staged for writing.
     std::size_t getNArrays() const { return _vec_names.size(); }
 
+    /// Returns a vector containing the names of columns in the file (assuming
+    /// the file *has* a header)
+    static std::vector<std::string> getColumnNames(std::string const& fname,
+                                                   char delim);
+
     /// Adds an index vector of size s to the CSV file
     void addIndexVectorForWriting(std::size_t s);
 
diff --git a/Tests/FileIO/TestCsvReader.cpp b/Tests/FileIO/TestCsvReader.cpp
index fd12ecb4dac..2d369857170 100644
--- a/Tests/FileIO/TestCsvReader.cpp
+++ b/Tests/FileIO/TestCsvReader.cpp
@@ -168,15 +168,20 @@ TEST_F(CsvInterfaceTest, CoordinateOrder)
 /// Getting single columns
 TEST_F(CsvInterfaceTest, GetColumn)
 {
+    std::vector<std::string> columns =
+        FileIO::CsvInterface::getColumnNames(_file_name, '\t');
+    ASSERT_EQ(7, columns.size());
     std::vector<std::string> names;
-    _result = FileIO::CsvInterface::readColumn<std::string>(_file_name, '\t', names, "name");
+    _result = FileIO::CsvInterface::readColumn<std::string>(_file_name, '\t', names, columns[4]);
     ASSERT_EQ(0, _result);
     ASSERT_EQ(10, names.size());
+    ASSERT_EQ("test_j", names[9]);
 
     std::vector<double> values;
-    _result = FileIO::CsvInterface::readColumn<double>(_file_name, '\t', values, "value_two");
+    _result = FileIO::CsvInterface::readColumn<double>(_file_name, '\t', values, columns[6]);
     ASSERT_EQ(2, _result);
     ASSERT_EQ(8, values.size());
+    ASSERT_NEAR(135, values[1], std::numeric_limits<double>::epsilon());
 }
 
 /// Dealing with non-existing column
-- 
GitLab