NeoPZ
csvtable.h
Go to the documentation of this file.
1 
5 #ifndef CSVTABLE_H
6 
7 //#include<sstream> // stringstream
8 #include<cctype>
9 #include<istream>// istream
10 #include<vector> // vector
11 #include <stdlib.h>
12 
13 using namespace std;
14 
16 template<class T>
18 
19  public:
20 
21  CSVTableColumn(const string& header)
22  {
23  setHeader(header);
24  }
25 
26  /* Gets the column name. */
27  const string& getHeader() const
28  {
29  return header;
30  }
31 
32  /* Sets the column name. */
33  void setHeader(const string& h)
34  {
35  header = h;
36  }
37 
38  /* Checks whether the header name is equal to h. */
39  bool isHeader(const string& h) const
40  {
41  return (header == h);
42  }
43 
44  /* Returns the number of rows. Headers do not count as rows. */
45  unsigned nRows() const
46  {
47  return data.size();
48  }
49 
53  unsigned addRows(unsigned nrows)
54  {
55  data.resize(data.size() + nrows);
56  return data.size();
57  }
58 
60  T& operator[](unsigned i)
61  {
62  if (i >= data.size()) {
63  cerr << "Error(" __FILE__ ":" << __LINE__ << "): Trying to access row " << i
64  << " but column has only " << data.size() << " rows." << endl;
65  exit(1);
66  }
67  return data[i];
68  }
69 
71  const T& operator[](unsigned i) const
72  {
73  if (i >= data.size()) {
74  cerr << "Error(" __FILE__ ":" << __LINE__ << "): Trying to access row " << i
75  << " but column has only " << data.size() << " rows." << endl;
76  exit(1);
77  }
78  return data[i];
79  }
80 
81  protected:
82 
83  string header;
84  vector<T> data;
85 
86 };
87 
88 template<class Tvar>
89 class CSVTable
90 {
91  public:
92  CSVTable() : nrows(0) {}
93 
98  unsigned addRows(unsigned n=1)
99  {
100  typename vector<CSVTableColumn<Tvar> >::iterator it;
101  nrows += n;
102  for (it = columns.begin(); it != columns.end(); it++) {
103  CSVTableColumn<Tvar>& col = *it;
104  col.addRows(n);
105  //assert col.nRows() == nrows
106  }
107  return (nrows-1);
108  }
109 
111  int getColIdx(const string& column_name)
112  {
113  int colidx = 0;
114  typename vector<CSVTableColumn<Tvar> >::iterator it;
115  for (it = columns.begin(); it != columns.end(); it++, colidx++) {
116  if (it->isHeader(column_name))
117  return colidx;
118  }
119  return -1;
120  }
121 
122  unsigned addColumn(const string& col_name)
123  {
124  CSVTableColumn<Tvar> col(col_name);
125  columns.push_back(col);
126  columns.back().addRows(nrows);
127  return (columns.size()-1);
128  }
129 
136  int setCell(unsigned row_idx, string col_name, string value, bool createNewCol = false)
137  {
138  if (nrows <= row_idx) return -1; // Return -1 row idx is out of bounds.
139 
140  int col_idx = getColIdx(col_name);
141 
142  if (col_idx < 0) {
143  if(!createNewCol)
144  return col_idx; // Return if error.
145  else {
146  col_idx = addColumn(col_name);
147  }
148  }
149  CSVTableColumn<Tvar>& col = columns[col_idx];
150  col[row_idx] = value;
151  return 0;
152  }
153  int setCell(unsigned row_idx, string col_name, int value, bool createNewCol = false)
154  {
155  stringstream str; str << value;
156  return setCell(row_idx, col_name, str.str(), createNewCol);
157  }
158  int setCell(unsigned row_idx, string col_name, long value, bool createNewCol = false)
159  {
160  stringstream str; str << value;
161  return setCell(row_idx, col_name, str.str(), createNewCol);
162  }
163  int setCell(unsigned row_idx, string col_name, bool value, bool createNewCol = false)
164  {
165  stringstream str; str << value;
166  return setCell(row_idx, col_name, str.str(), createNewCol);
167  }
168  int setCell(unsigned row_idx, string col_name, unsigned value, bool createNewCol = false)
169  {
170  stringstream str; str << value;
171  return setCell(row_idx, col_name, str.str(), createNewCol);
172  }
173  int setCell(unsigned row_idx, string col_name, double value, bool createNewCol = false)
174  {
175  stringstream str; str.precision(6); str << std::fixed << value;
176  return setCell(row_idx, col_name, str.str(), createNewCol);
177  }
178  int setCell(unsigned row_idx, string col_name, float value, bool createNewCol = false)
179  {
180  stringstream str; str << value;
181  return setCell(row_idx, col_name, str.str(), createNewCol);
182  }
183 
184  unsigned nRows() const
185  {
186  return nrows;
187  }
188 
189  void write(ostream& os) const
190  {
191  const char* comma = "";
192  typename vector<CSVTableColumn<Tvar> >::const_iterator it;
193 
194  for (it = columns.begin(); it != columns.end(); it++) {
195  os << comma << it->getHeader();
196  comma = ",";
197  }
198 
199  for (unsigned i=0; i < nrows; i++) {
200  comma = "";
201  os << endl;
202  for (it = columns.begin(); it != columns.end(); it++) {
203  os << comma << (*it)[i];
204  comma = ",";
205  }
206  }
207  }
208 
214  int read(istream& is)
215  {
216  string line;
217  vector<string> tokens;
218  int ret = 0;
219 
220  /* reset table */
221  columns.clear();
222  nrows = 0;
223 
224  if (is.eof()) return -1;
225 
226  /* read the column headers. */
227  getline(is, line);
228  if (line.size() == 0) return -1;
229 
230  split(tokens, line, ",");
231  if(tokens.size() == 0) return -1;
232 
233  /* Build columns. */
234  vector<string>::iterator tit;
235  for (tit = tokens.begin(); tit != tokens.end(); tit++) {
236  string hd = *tit;
237  trim(hd);
238  addColumn(hd);
239  }
240 
241  unsigned ncols = columns.size();
242 
243  while(!is.eof()) {
244  string line;
245  vector<string> tokens;
246  /* read the row. */
247  getline(is, line);
248  //cout << "Reading line " << nrows << ": " << line << endl;
249  split(tokens, line, ",");
250 
251  unsigned ntokens = tokens.size();
252  if (ntokens != ncols) ret = 1;
253 
254  /*Fill row. */
255  for (unsigned i=0; i<ncols; i++) {
256  CSVTableColumn<Tvar>& col = columns[i];
257  col.addRows(1);
258  if (i < ntokens) {
259  string& v = tokens[i];
260  col[nrows] = v;
261  }
262  }
263  nrows++;
264  }
265 
266  return ret;
267  }
268 
269  protected:
270 
271  void split( vector<string> & theStringVector,
272  const string & theString,
273  const string & theDelimiter)
274  {
275  size_t start = 0, end = 0;
276  while ( end != string::npos)
277  {
278  end = theString.find( theDelimiter, start);
279  // If at end, use length=maxLength. Else use length=end-start.
280  theStringVector.push_back( theString.substr( start,
281  (end == string::npos) ? string::npos : end - start));
282  // If at end, use start=maxSize. Else use start=end+delimiter.
283  start = ( ( end > (string::npos - theDelimiter.size()) )
284  ? string::npos : end + theDelimiter.size());
285  }
286  }
287 
288  // trim from both ends
289  static inline string &trim(string &s) {
290 
291  /* If first is space, eat the consecutive spaces. */
292  string::iterator first = s.begin();
293  while((first != s.end()) && isspace(*first)) first++;
294  if (first != s.begin()) s.erase(s.begin(), first-1);
295 
296  if (s.size() == 0) return s;
297 
298  /* If we reach this point, there is at least one non-space character. */
299  /* If last is space, eat the consecutive spaces. */
300  string::iterator last = s.end()-1;
301  /* If first is space, eat the consecutive spaces. */
302  while(isspace(*last)) last--;
303  if (last != s.end()) s.erase(++last, s.end());
304 
305  return s;
306  }
307 
309  vector<CSVTableColumn<Tvar> > columns;
310 
311  unsigned nrows;
312 };
313 
316 
317 #endif // CSVTABLE_H
318 
static string & trim(string &s)
Definition: csvtable.h:289
unsigned addRows(unsigned nrows)
Definition: csvtable.h:53
int setCell(unsigned row_idx, string col_name, string value, bool createNewCol=false)
Definition: csvtable.h:136
int setCell(unsigned row_idx, string col_name, long value, bool createNewCol=false)
Definition: csvtable.h:158
int setCell(unsigned row_idx, string col_name, float value, bool createNewCol=false)
Definition: csvtable.h:178
void split(vector< string > &theStringVector, const string &theString, const string &theDelimiter)
Definition: csvtable.h:271
int setCell(unsigned row_idx, string col_name, int value, bool createNewCol=false)
Definition: csvtable.h:153
clarg::argBool h("-h", "help message", false)
void write(ostream &os) const
Definition: csvtable.h:189
const string & getHeader() const
Definition: csvtable.h:27
int read(istream &is)
Definition: csvtable.h:214
unsigned addColumn(const string &col_name)
Definition: csvtable.h:122
vector< T > data
Definition: csvtable.h:84
int setCell(unsigned row_idx, string col_name, unsigned value, bool createNewCol=false)
Definition: csvtable.h:168
T & operator[](unsigned i)
Definition: csvtable.h:60
CSVTableColumn(const string &header)
Definition: csvtable.h:21
unsigned addRows(unsigned n=1)
Definition: csvtable.h:98
CSVTable()
Definition: csvtable.h:92
unsigned nRows() const
Definition: csvtable.h:184
vector< CSVTableColumn< Tvar > > columns
Definition: csvtable.h:309
string header
Definition: csvtable.h:83
unsigned nrows
Definition: csvtable.h:311
int setCell(unsigned row_idx, string col_name, bool value, bool createNewCol=false)
Definition: csvtable.h:163
void setHeader(const string &h)
Definition: csvtable.h:33
int getColIdx(const string &column_name)
Definition: csvtable.h:111
unsigned nRows() const
Definition: csvtable.h:45
int setCell(unsigned row_idx, string col_name, double value, bool createNewCol=false)
Definition: csvtable.h:173
const T & operator[](unsigned i) const
Definition: csvtable.h:71
CSVTable< string > CSVStringTable
Definition: csvtable.h:315
bool isHeader(const string &h) const
Definition: csvtable.h:39