38 #ifndef LIB_STAT_CSV_H 39 #define LIB_STAT_CSV_H 64 const string MATCH_SINGLE_TOKEN { R
"~(([^,;"\s]*)\s*)~"}; 65 const string MATCH_QUOTED_TOKEN { R
"~("([^"]*)"\s*)~" }; 66 const string MATCH_DELIMITER { R
"~((?:^|,|;)\s*)~" }; 68 const regex FIND_DELIMITER_TOKEN{
"[,;]"};
70 const regex ACCEPT_FIELD{ MATCH_DELIMITER +
"(?:"+ MATCH_QUOTED_TOKEN +
"|"+ MATCH_SINGLE_TOKEN +
")" 73 template<
typename VAL>
75 format4Csv (VAL
const& val)
77 if constexpr (std::is_floating_point_v<VAL>)
78 return util::showDecimal (val);
80 auto res = util::toString (val);
81 if constexpr (std::is_arithmetic_v<VAL>)
92 template<
typename VAL>
96 csv += (0 == csv.length()?
"":
",")
108 using value_type = string;
111 CSVLine (ELMS&& ...items)
113 meta::forEach (std::make_tuple (items...)
114 ,[
this](
auto const& it){ *this += it; }
122 operator+= (X
const& x)
124 stat::appendCsvField (*
this, x);
141 : std::vector<CSVLine>
143 using VecCSV = std::vector<CSVLine>;
145 CSVData (std::initializer_list<string> lines)
146 : VecCSV(detectHeader(lines))
149 CSVData (std::initializer_list<string> header
150 ,std::initializer_list<CSVLine> data)
152 reserve (data.size()+1);
153 appendHeaderLine(*
this, header);
154 for (
CSVLine const& line : data)
161 operator string()
const 163 std::ostringstream buffer;
164 for (
string const& line : *
this)
165 buffer << line <<
'\n';
172 containsCSV (
string const& line)
174 return std::regex_search (line, FIND_DELIMITER_TOKEN);
178 appendHeaderLine (VecCSV& data, std::initializer_list<string>
const& input)
181 for (
string const& s : input)
183 data.emplace_back (move(header));
187 detectHeader (std::initializer_list<string> input)
190 if (input.size() > 0 and containsCSV(*input.begin()))
192 csv.reserve (input.size());
193 for (
string const& s : input)
194 csv.emplace_back (s);
197 appendHeaderLine (csv, input);
205 template<
typename TAR>
209 std::istringstream converter{encodedVal};
212 if (converter.fail())
219 parseAs (
string const& encodedBool)
221 return util::boolVal(encodedBool);
244 string const& line_{};
257 : RegexSearchIter(line, ACCEPT_FIELD)
261 explicit operator bool()
const 269 string operator*()
const 271 if (not isValid()) fail();
273 return mat[2].matched? mat[2]
282 pos_ = curr()->position() + curr()->length();
283 util::RegexSearchIter::operator ++();
284 if (pos_ < line_.length() and not isValid())
298 return curr() != end()
299 and pos_ == size_t(curr()->position())
300 and not curr()->empty();
306 return curr() != end()
314 if (pos_ >= line_.length())
319 % line_.substr(0,pos_) % line_.substr(pos_)};
321 if (pos_ !=
size_t(curr()->position()))
324 % 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.