#ifndef CSVFILE_HPP #define CSVFILE_HPP #include #include #include #include #include #include #include #include class csvFile; inline static csvFile &endrow(csvFile &file); inline static csvFile &flush(csvFile &file); class csvFile { std::ofstream fs_; bool is_first_; const std::string separator_; const std::string escape_seq_; const std::string special_chars_; public: csvFile(const std::filesystem::path &filename, const bool &overwrite, const std::string separator = ",") : fs_(), is_first_(true), separator_(separator), escape_seq_("\""), special_chars_("\"") { fs_.exceptions(std::ios::failbit | std::ios::badbit); if (filename.empty()) { fs_.copyfmt(std::cout); fs_.clear(std::cout.rdstate()); fs_.basic_ios::rdbuf(std::cout.rdbuf()); } else { if (!std::filesystem::exists(filename)) { std::ofstream outfile(filename); outfile.close(); } overwrite ? fs_.open(filename, std::ios::trunc) : fs_.open(filename, std::ios::app); } } ~csvFile() { flush(); fs_.close(); } void flush() { fs_.flush(); } void endrow() { fs_ << std::endl; is_first_ = true; } csvFile &operator<<(csvFile &(*val)(csvFile &)) { return val(*this); } csvFile &operator<<(const char *val) { return write(escape(val)); } csvFile &operator<<(const std::string &val) { return write(escape(val)); } template csvFile &operator<<(const T &val) { return write(val); } static std::vector> parse(const std::filesystem::path &csvFilepath) { std::vector> resultCSV; if (!std::filesystem::exists(csvFilepath)) { std::cerr << "The file does not exist:" << csvFilepath.string() << std::endl; return resultCSV; } std::ifstream inputfile(csvFilepath.string().c_str()); if (!inputfile.is_open()) { std::cerr << "Can't open file:" << csvFilepath.string() << std::endl; return resultCSV; } std::vector row; std::string line; using Tokenizer = boost::tokenizer>; while (std::getline(inputfile, line)) { Tokenizer tokenizer(line); const int numOfCols = std::distance(tokenizer.begin(), tokenizer.end()); row.resize(numOfCols); std::copy(tokenizer.begin(), tokenizer.end(), row.begin()); // std::transform(tokenizer.begin(), tokenizer.end(), row.begin(), [](const std::string &el) { // return boost::lexical_cast(el); // }); resultCSV.push_back(row); } return resultCSV; } private: template csvFile &write(const T &val) { if (!is_first_) { fs_ << separator_; } else { is_first_ = false; } fs_ << val; return *this; } std::string escape(const std::string &val) { std::ostringstream result; result << '"'; std::string::size_type to, from = 0u, len = val.length(); while (from < len && std::string::npos != (to = val.find_first_of(special_chars_, from))) { result << val.substr(from, to - from) << escape_seq_ << val[to]; from = to + 1; } result << val.substr(from) << '"'; return result.str(); } }; inline static csvFile &endrow(csvFile &file) { file.endrow(); return file; } inline static csvFile &flush(csvFile &file) { file.flush(); return file; } #endif // CSVFILE_HPP