#pragma once #include #include #include #include #include class CsvDataLoader { public: CsvDataLoader(const std::vector& csv_files, char delim = ',') : delim(delim) { for(const auto& f : csv_files) { if(f == "-") { streams.push_back(&std::cin); }else{ std::ifstream* pFile = new std::ifstream(f); owned_streams.emplace_back(pFile); streams.push_back(pFile); PANGO_ASSERT(pFile->is_open()); } } } bool SkipStreamRows(const std::vector& rows_to_skip) { if(rows_to_skip.size()) { PANGO_ASSERT(rows_to_skip.size() == streams.size()); std::vector dummy_row; for(size_t i=0; i < streams.size(); ++i) { for(size_t r=0; r < rows_to_skip[i]; ++r) { if(!AppendColumns(dummy_row, *streams[i], delim)) { return false; } } } } return true; } bool ReadRow(std::vector& row) { row.clear(); for(auto& s : streams) { if(!AppendColumns(row, *s, delim)) { return false; } } return true; } private: static bool AppendColumns(std::vector& cols, std::istream& s, char delim) { // Read line from stream std::string row; std::getline(s,row); // Failure if no lines to read if(!s.good()) return false; std::stringstream row_stream(row); std::string cell; // Read cells while(std::getline(row_stream, cell, delim)) { cols.push_back(cell); } // Check for an empty trailing cell if (!row_stream && cell.empty()) { cols.push_back(""); } return true; } char delim; std::vector streams; std::vector> owned_streams; };