#ifndef EASY_H #define EASY_H #include #include #include #include #include #include #include namespace easy { template class vector_helper : public std::vector { protected: inline void check_stream(const std::basic_ios& stream, const std::string& file_name) { if (!stream.good()) { std::cerr << "Could not properly access file " << file_name << std::endl; throw(std::runtime_error("Could not properly access file " + file_name)); } } public: template inline vector_helper(Args... args) : std::vector(args...) {} // std::vector does not necessarily return T&, for example when T is bool, we have to get the return type of the method inline decltype(std::declval>().operator[](0)) operator [] (unsigned int index) { if (index >= this->size()) { std::cerr << "Error: reading index " << index << " of vector sized " << this->size() << std::endl; throw(std::logic_error("Reading index " + std::to_string(index) + " of vector sized " + std::to_string(this->size()))); } return std::vector::operator[](index); } inline decltype(std::declval>().operator[](0)) operator [] (unsigned int index) const { if (index >= this->size()) { std::cerr << "Error: reading index " << index << " of vector sized " << this->size() << std::endl; throw(std::logic_error("Reading index " + std::to_string(index) + " of vector sized " + std::to_string(this->size()))); } return std::vector::operator[](index); } }; template class vector : public vector_helper { public: template inline vector(Args... args) : vector_helper(args...) {} inline vector(const char* file_name, char separator = '\n') : vector(std::string(file_name), separator) {} inline vector(const std::string& file_name, char separator = '\n') { std::ifstream in(file_name); this->check_stream(in, file_name); std::string line; while (std::getline(in, line, separator)) { if (line.empty()) continue; std::stringstream reading(line); T read; reading >> read; this->push_back(read); } } inline void write_file(const std::string& name, char separator = '\n') { std::ofstream out(name); this->check_stream(out, name); for (unsigned int i = 0; i < this->size(); i++) out << std::vector::operator[](i) << separator; } }; template class vector> : public vector_helper> { public: template inline vector(Args... args) : vector_helper>(args...) {} inline vector(const char* file_name, char line_separator = '\n', char column_separator = '\t') : vector(std::string(file_name), line_separator, column_separator) {} inline vector(const std::string& file_name, char line_separator = '\n', char column_separator = '\t') { std::ifstream in(file_name); this->check_stream(in, file_name); std::string line; while (std::getline(in, line, line_separator)) { std::stringstream lineStream(line); std::string cell; easy::vector subResult; while (std::getline(lineStream, cell, column_separator)) { if (cell.empty()) continue; std::stringstream reading(cell); T read; reading >> read; subResult.push_back(read); } subResult.shrink_to_fit(); this->push_back(easy::vector()); this->back().swap(subResult); } this->shrink_to_fit(); } inline void write_file(const std::string& name, char line_separator = '\n', char column_separator = '\t') { std::ofstream out(name); this->check_stream(out, name); for (unsigned int i = 0; i < this->size(); i++) for (unsigned int j = 0; j < std::vector>::operator[](i).size(); j++) out << std::vector>::operator[](i)[j] << ((j < std::vector>::operator[](i).size() - 1) ? column_separator : line_separator); } }; template class vector> : public vector> { public: template inline vector(Args... args) : vector>(args...) {} }; template inline void write_file(T vector, Args... args) { vector.write_file(args...); } template inline std::ostream& operator<<(std::ostream& out, const vector& vec) { out << "("; for (unsigned int i = 0; i < vec.size(); i++) { if (i) out << ", "; out << vec[i]; } out << ")"; return out; } } #endif