47 #ifndef LIB_STAT_CSV_H 48 #define LIB_STAT_CSV_H 73 const string MATCH_SINGLE_TOKEN { R
"~(([^,;"\s]*)\s*)~"}; 74 const string MATCH_QUOTED_TOKEN { R
"~("([^"]*)"\s*)~" }; 75 const string MATCH_DELIMITER { R
"~((?:^|,|;)\s*)~" }; 77 const regex FIND_DELIMITER_TOKEN{
"[,;]"};
79 const regex ACCEPT_FIELD{ MATCH_DELIMITER +
"(?:"+ MATCH_QUOTED_TOKEN +
"|"+ MATCH_SINGLE_TOKEN +
")" 82 template<
typename VAL>
84 format4Csv (VAL
const& val)
86 if constexpr (std::is_floating_point_v<VAL>)
87 return util::showDecimal (val);
89 auto res = util::toString (val);
90 if constexpr (std::is_arithmetic_v<VAL>)
101 template<
typename VAL>
105 csv += (0 == csv.length()?
"":
",")
117 using value_type = string;
120 CSVLine (ELMS&& ...items)
122 meta::forEach (std::make_tuple (items...)
123 ,[
this](
auto const& it){ *this += it; }
131 operator+= (X
const& x)
133 stat::appendCsvField (*
this, x);
150 : std::vector<CSVLine>
152 using VecCSV = std::vector<CSVLine>;
154 CSVData (std::initializer_list<string> lines)
155 : VecCSV(detectHeader(lines))
158 CSVData (std::initializer_list<string> header
159 ,std::initializer_list<CSVLine> data)
161 reserve (data.size()+1);
162 appendHeaderLine(*
this, header);
163 for (
CSVLine const& line : data)
170 operator string()
const 172 std::ostringstream buffer;
173 for (
string const& line : *
this)
174 buffer << line <<
'\n';
181 containsCSV (
string const& line)
183 return std::regex_search (line, FIND_DELIMITER_TOKEN);
187 appendHeaderLine (VecCSV& data, std::initializer_list<string>
const& input)
190 for (
string const& s : input)
192 data.emplace_back (move(header));
196 detectHeader (std::initializer_list<string> input)
199 if (input.size() > 0 and containsCSV(*input.begin()))
201 csv.reserve (input.size());
202 for (
string const& s : input)
203 csv.emplace_back (s);
206 appendHeaderLine (csv, input);
214 template<
typename TAR>
218 std::istringstream converter{encodedVal};
221 if (converter.fail())
228 parseAs (
string const& encodedBool)
230 return util::boolVal(encodedBool);
253 string const& line_{};
266 : RegexSearchIter(line, ACCEPT_FIELD)
270 explicit operator bool()
const 278 string operator*()
const 280 if (not isValid()) fail();
282 return mat[2].matched? mat[2]
291 pos_ = curr()->position() + curr()->length();
292 util::RegexSearchIter::operator ++();
293 if (pos_ < line_.length() and not isValid())
307 return curr() != end()
308 and pos_ == size_t(curr()->position())
309 and not curr()->empty();
315 return curr() != end()
323 if (pos_ >= line_.length())
328 % line_.substr(0,pos_) % line_.substr(pos_)};
330 if (pos_ !=
size_t(curr()->position()))
333 % line_.substr(0,pos_) % line_.substr(pos_)};
Wrapper to simplify notation in tests.
void appendCsvField(string &csv, VAL const &val)
Format and append a data value to a CSV string representation.
A string with the ability to construct or append the CSV-rendering of data fields.
Singleton holder for NIL or default value objects.
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
Singleton-style holder for NIL or default values.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Metaprogramming with tuples-of-types and the std::tuple record.
TAR parseAs(string const &encodedVal)
parse string representation into typed value
Derived specific exceptions within Lumiera's exception hierarchy.
Lumiera error handling (C++ interface).
wrapped regex iterator to allow usage in foreach loops
Convenience wrappers and helpers for dealing with regular expressions.
Parser to split one line of CSV data into fields.