#ifndef CSVFILE_HPP #define CSVFILE_HPP #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::string 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( std::filesystem::path("../OptimizationResults") .append("statistics.csv"))) { std::ofstream outfile(std::filesystem::path("../OptimizationResults") .append("statistics.csv") .string()); 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); } 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