78#ifndef LIB_STAT_DATA_H
79#define LIB_STAT_DATA_H
120 template<
typename VAL>
149 operator VAL
const&()
const
151 return unConst(
this)->get();
157 return get() = std::forward<X> (newVal);
207 static constexpr size_t columnCnt = std::tuple_size_v<decltype(std::declval<TAB>().allColumns())>;
212 return 0 == this->
size();
218 if (0 == columnCnt)
return 0;
219 size_t rowCnt = std::numeric_limits<size_t>::max();
223 rowCnt = min (rowCnt, col.data.size());
232 csv.reserve (
size()+1);
235 swap (csv[0], header);
252 col.data.resize (siz);
265 col.data.emplace_back (col.data.back());
276 size_t siz = col.data.size();
277 col.data.resize (siz>0? siz-1 : 0);
287 col.data.reserve(expectedCapacity);
304 if (isnil (csv))
return;
306 for (
size_t row=1; row<csv.size(); ++row)
307 if (not isnil (csv[row]))
315 save (
size_t lineLimit =std::numeric_limits<size_t>::max()
316 ,
bool backupOld =
false)
319 throw error::Logic{
"Unable to save DataFile without filename given."};
322 newFilename +=
".tmp";
324 std::ofstream csvFile{newFilename, std::ios_base::out | std::ios_base::trunc};
325 if (not csvFile.good())
344 ,
size_t lineLimit =std::numeric_limits<size_t>::max())
347 if (fs::exists(newStorage))
350 if (not (newStorage.parent_path().empty()
351 or fs::exists(newStorage.parent_path())))
353 % newStorage.filename() % newStorage.parent_path()};
367 ,std::forward<OP> (doIt));
381 if (not csvFile.good())
384 std::deque<string> rawLines;
385 for (
string line; std::getline(csvFile, line); )
386 rawLines.emplace_back (move(line));
388 if (rawLines.size() < 1)
return;
395 for (
size_t row = rawLines.size()-1; 0<row; --row)
396 if (not isnil(rawLines[row]))
402 saveData (std::ofstream& csvFile,
size_t lineLimit)
407 lineLimit =
size() > lineLimit?
size()-lineLimit : 0;
409 for (
size_t row =
size(); lineLimit < row; --row)
421 if (*header != col.header)
423 "Expecting column(%s) but found \"%s\""}
452 if (csv.isParseFail())
456 % csv.getParsedFieldCnt() % columnCnt % line};
459 using Value = std::remove_reference<
decltype(col)>::type::ValueType;
460 col.get() = parseAs<Value>(*csv);
473 throw error::Logic{
"Attempt to access data from empty DataTable."};
474 if (rownum >= this->size())
476 % rownum % (size()-1)};
482 csvLine += col.data.at(rownum);
Parser to split one line of CSV data into fields.
Table with data values, stored persistently as CSV file.
DataTable(CSVData const &csv)
DataTable(fs::path csvFile="")
void save(size_t lineLimit=std::numeric_limits< size_t >::max(), bool backupOld=false)
CSVData renderCSV() const
void verifyHeaderSpec(string headerLine)
void appendFrom(CSVData const &csv)
void saveAs(fs::path newStorage, size_t lineLimit=std::numeric_limits< size_t >::max())
void reserve(size_t expectedCapacity)
void saveData(std::ofstream &csvFile, size_t lineLimit)
void forAllColumns(OP &&doIt) const
apply a generic Lambda to all columns
static constexpr size_t columnCnt
void appendRowFromCSV(string line)
CSVLine generateHeaderSpec() const
CSVLine formatCSVRow(size_t rownum) const
Derived specific exceptions within Lumiera's exception hierarchy.
Types marked with this mix-in may be moved but not copied.
A front-end for using printf-style formatting.
Encoding and decoding of data into CSV format.
Lumiera error handling (C++ interface).
Includes the C++ Filesystem library and provides some convenience helpers.
Implementation namespace for support and library code.
LumieraError< LERR_(STATE)> State
LumieraError< LERR_(LOGIC)> Logic
LumieraError< LERR_(CONFIG), Invalid > Config
fs::path consolidated(fs::path rawPath)
resolves symlinks, ~ (Unix home dir) and relative specs
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
bool isnil(lib::time::Duration const &dur)
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Wrapper to simplify notation in tests.
A string with the ability to construct or append the CSV-rendering of data fields.
Descriptor and Accessor for a data column within a DataTable table.
VAL & operator=(X &&newVal)
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...