table.h 3.39 KB
#ifndef STIM_TABLE_H
#define STIM_TABLE_H

#include <type_traits>
#include <vector>
#include <sstream>
#include <fstream>

namespace stim{

	class table{

		std::vector< std::vector< std::string > > TABLE;

		size_t x;											//current x and y positions for adding elements to the table
		size_t y;

		void init(){
			x = y = 0;
			TABLE.resize(1);								//create a single row
			TABLE[0].clear();								//make sure that the row is empty
		}
	public:

		table(){
			init();
		}

		void new_column(){
			x = 0;											//reset to the first position of the column
			y++;											//increment the current row position
			TABLE.push_back( std::vector<std::string>() );	//push an empty row
		}

		template<typename T>
		T operator<<(T i){
			std::stringstream ss;
			if(std::is_fundamental<T>())						//if the data type is numeric
				ss<<std::setprecision(std::numeric_limits<T>::digits10 + 3);	//set the precision to account for all digits
			ss<<i;
			TABLE[y].push_back(ss.str());
			x++;
			return i;
		}

		std::string str(){
			std::stringstream ss;
			for(size_t yi = 0; yi < TABLE.size(); yi++){
				for(size_t xi = 0; xi < TABLE[yi].size(); xi++){
					if(xi != 0) ss<<", ";
					ss<<TABLE[yi][xi];
				}
				ss<<std::endl;
			}
			return ss.str();
		}

		void save_ascii(std::string filename, char col_delim = ',', char row_delim = '\n'){
			std::ofstream outfile(filename);
			for(size_t yi = 0; yi < TABLE.size(); yi++){
				if(yi != 0 && TABLE[yi].size() > 0) outfile<<row_delim;
				for(size_t xi = 0; xi < TABLE[yi].size(); xi++){
					if(xi != 0) outfile<<col_delim;
					outfile<<TABLE[yi][xi];
				}
			}
		}

		void read_ascii(std::string filename, char col_delim = ',', char row_delim = '\n'){
			std::ifstream infile(filename);						//open an ascii file for reading
			TABLE.clear();									//empty out the table

			std::string line;
			while(!infile.eof()){
				std::getline(infile, line, row_delim);		//read a line from the file using the row delimiter
				size_t pos = 0;
				std::string token;
				std::vector< std::string > row;
				while ((pos = line.find(col_delim)) != std::string::npos) {
					token = line.substr(0, pos);
					row.push_back(token);
					line.erase(0, pos + 1);
				}
				token = line.substr(0, std::string::npos);		//read the last column
				row.push_back(token);							//push it into the table
				TABLE.push_back(row);		//add an empty vector to the table
			}
		}

		/// Returns a vector representation of the table by casting to the specified template
		template<typename T>
		std::vector< std::vector<T> > get_vector(){
			std::vector< std::vector<T> > result;
			result.resize(TABLE.size());							//initialize the first dimension of the returned table
			for(size_t i = 0; i < TABLE.size(); i++){				//for each row
				result[i].resize(TABLE[i].size());					//initialize the number of columns in this row
				for(size_t j = 0; j < TABLE[i].size(); j++){			//for each column
					std::stringstream ss(TABLE[i][j]);
					ss >> result[i][j];
				}
			}
			return result;											//return the casted table
		}

		size_t rows(){
			return TABLE.size();
		}

		size_t cols(size_t ri){
			return TABLE[ri].size();
		}

		//returns the maximum number of columns in the table
		size_t cols(){
			size_t max_c = 0;
			for(size_t ri = 0; ri < rows(); ri++){
				max_c = std::max(max_c, cols(ri));
			}
			return max_c;
		}

		std::string operator()(size_t ri, size_t ci){
			return TABLE[ri][ci];
		}

	};
};


#endif