OGS
CsvInterface.h
Go to the documentation of this file.
1
14#pragma once
15
16#include <any>
17#include <array>
18#include <fstream>
19#include <iterator>
20#include <limits>
21#include <list>
22#include <string>
23#include <typeinfo>
24#include <vector>
25
26#include "BaseLib/IO/Writer.h"
27#include "BaseLib/Logging.h"
28#include "BaseLib/StringTools.h"
29
30namespace GeoLib
31{
32class Point;
33}
34
35namespace FileIO
36{
41{
42public:
45
47 std::size_t getNArrays() const { return _vec_names.size(); }
48
51 static std::vector<std::string> getColumnNames(std::string const& fname,
52 char delim);
53
55 void addIndexVectorForWriting(std::size_t s);
56
58 void setCsvHeader(bool write_header) { _writeCsvHeader = write_header; }
59
63 template <typename T>
64 bool addVectorForWriting(std::string const& vec_name,
65 std::vector<T> const& vec)
66 {
67 static_assert(
68 std::is_same_v<T, std::string> || std::is_same_v<T, double> ||
69 std::is_same_v<T, int>,
70 "CsvInterface can only write vectors of strings, doubles or ints.");
71
72 if (!_data.empty())
73 {
74 std::size_t const vec_size(getVectorSize(0));
75 if (vec_size != vec.size())
76 {
77 ERR("Vector size does not match existing data (should be "
78 "{:d}).",
79 vec_size);
80 return false;
81 }
82 }
83
84 _vec_names.push_back(vec_name);
85 _data.push_back(vec);
86 return true;
87 }
88
90 bool write() override;
91
101 static int readPoints(std::string const& fname, char delim,
102 std::vector<GeoLib::Point*>& points);
103
119 static int readPoints(std::string const& fname, char delim,
120 std::vector<GeoLib::Point*>& points,
121 std::string const& x_column_name,
122 std::string const& y_column_name,
123 std::string const& z_column_name = "");
124
139 static int readPoints(
140 std::string const& fname, char delim,
141 std::vector<GeoLib::Point*>& points, std::size_t x_column_idx,
142 std::size_t y_column_idx,
143 std::size_t z_column_idx = std::numeric_limits<std::size_t>::max());
144
154 template <typename T>
155 static std::pair<int, std::vector<T>> readColumn(
156 std::string const& fname, char delim, std::string const& column_name)
157 {
158 std::ifstream in(fname.c_str());
159 if (!in.is_open())
160 {
161 ERR("CsvInterface::readColumn(): Could not open file {:s}.", fname);
162 return {-1, {}};
163 }
164
165 std::string line;
166 std::getline(in, line);
167 std::size_t const column_idx =
168 CsvInterface::findColumn(line, delim, column_name);
169 if (column_idx == std::numeric_limits<std::size_t>::max())
170 {
171 ERR("Column '{:s}' not found in file header.", column_name);
172 return {-1, {}};
173 }
174 return readColumn<T>(in, delim, column_idx);
175 }
176
177 template <typename T>
178 static std::pair<int, std::vector<T>> readColumn(std::string const& fname,
179 char delim,
180 std::size_t column_idx)
181 {
182 std::ifstream in(fname.c_str());
183 if (!in.is_open())
184 {
185 ERR("CsvInterface::readColumn(): Could not open file {:s}.", fname);
186 return {-1, {}};
187 }
188 return readColumn<T>(in, delim, column_idx);
189 }
190
191private:
193 static int readPoints(std::ifstream& in, char delim,
194 std::vector<GeoLib::Point*>& points,
195 std::array<std::size_t, 3> const& column_idx);
196
198 template <typename T>
199 static std::pair<int, std::vector<T>> readColumn(std::ifstream& in,
200 char delim,
201 std::size_t column_idx)
202 {
203 std::vector<T> data_array;
204 std::string line;
205 std::size_t line_count(0);
206 int error_count(0);
207 while (std::getline(in, line))
208 {
209 line_count++;
210 std::list<std::string> const fields =
211 BaseLib::splitString(line, delim);
212
213 if (fields.size() < column_idx + 1)
214 {
215 ERR("Line {:d} contains not enough columns of data. Skipping "
216 "line...",
217 line_count);
218 error_count++;
219 continue;
220 }
221 auto it = fields.begin();
222 std::advance(it, column_idx);
223
224 std::istringstream stream(*it);
225 T value;
226 if (!(stream >> value))
227 {
228 ERR("Error reading value in line {:d}.", line_count);
229 error_count++;
230 continue;
231 }
232
233 data_array.push_back(value);
234 }
235 return {error_count, data_array};
236 }
237
240 static std::size_t findColumn(std::string const& line, char delim,
241 std::string const& column_name);
242
244 std::size_t getVectorSize(std::size_t idx) const;
245
251 void writeValue(std::size_t vec_idx, std::size_t in_vec_idx);
252
253 bool _writeCsvHeader{true};
254 std::vector<std::string> _vec_names;
255 std::vector<std::any> _data;
256};
257
258} // namespace FileIO
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
Definition of string helper functions.
Definition of the Writer class.
Base class which enables writing an object to string, stringstream or file.
Definition Writer.h:32
std::vector< std::any > _data
void writeValue(std::size_t vec_idx, std::size_t in_vec_idx)
std::vector< std::string > _vec_names
static std::vector< std::string > getColumnNames(std::string const &fname, char delim)
static std::pair< int, std::vector< T > > readColumn(std::string const &fname, char delim, std::size_t column_idx)
bool addVectorForWriting(std::string const &vec_name, std::vector< T > const &vec)
void setCsvHeader(bool write_header)
Stores if the CSV file to be written should include a header or not.
static std::size_t findColumn(std::string const &line, char delim, std::string const &column_name)
void addIndexVectorForWriting(std::size_t s)
Adds an index vector of size s to the CSV file.
static std::pair< int, std::vector< T > > readColumn(std::ifstream &in, char delim, std::size_t column_idx)
Actual column reader for public methods.
std::size_t getVectorSize(std::size_t idx) const
Returns the size of the vector with the given index.
std::size_t getNArrays() const
Returns the number of vectors currently staged for writing.
CsvInterface()
Constructor (only needed for writing files)
bool write() override
Writes the CSV file.
static std::pair< int, std::vector< T > > readColumn(std::string const &fname, char delim, std::string const &column_name)
static int readPoints(std::string const &fname, char delim, std::vector< GeoLib::Point * > &points)
std::vector< std::string > splitString(std::string const &str)
TemplateElement< PointRule1 > Point
Definition Point.h:20