#ifndef CSV_HPP #define CSV_HPP 1 #include #include #include #include #include #include namespace csv { template struct csv_delim : std::ctype { csv_delim() : std::ctype(get_table()) {} static mask const *get_table() { static mask rc[table_size]; rc[T] = std::ctype_base::space; rc['\n'] = std::ctype_base::space; return &rc[0]; } }; template class CSVFile { public: struct CSVLine { std::tuple data; CSVLine(const std::string &line) { std::istringstream in(line); in.imbue(std::locale(std::locale(), new csv_delim)); read_elements(in, std::make_index_sequence{}); } template void read_elements(std::istream &in, std::index_sequence) { std::initializer_list{read_element(in, std::get(data))...}; } template bool read_element(std::istream &in, T &value) { in >> value; return true; } }; struct Reader { private: std::vector m_lines; public: Reader() {} Reader(CSVFile *parent) { for(std::string line; std::getline(parent->m_rfile, line);) { m_lines.emplace_back(line); } } std::vector> get() const { std::vector> r; for(auto &line : m_lines) r.push_back(line.data); return r; } }; struct Writer { private: std::vector> m_data; public: void put(std::tuple line) { m_data.push_back(line); } void write(CSVFile *parent) { for(auto &line : m_data) { write_line(parent, line, std::make_index_sequence{}); parent->m_wfile.seekp(-1, std::ios_base::end); parent->m_wfile << "\n"; } } template void write_line(CSVFile *parent, std::tuple line, std::index_sequence) { std::initializer_list{write_element(parent, std::get(line))...}; } template bool write_element(CSVFile *parent, T &value) { parent->m_wfile << value << Seperator; return true; } }; friend struct Reader; friend struct Writer; CSVFile(const std::string &path, bool write = false) { //std::ios_base::iostate emask = m_file.exceptions() | std::ios::failbit; if(!write) { m_rfile.open(path); m_reader = Reader(this); }else{ m_wfile.open(path); } } ~CSVFile() { m_rfile.close(); m_wfile.close(); } const std::tuple operator[](std::size_t i) { return m_reader.m_lines[i].data; } std::size_t size() const { return m_reader.m_lines.size(); } std::vector> get() const { return m_reader.get(); } void put(std::tuple vals) { m_writer.put(vals); } void write() { m_writer.write(this); } protected: std::ifstream m_rfile; std::ofstream m_wfile; Reader m_reader; Writer m_writer; }; } #endif