Stride Reference Manual  - generated for commit 9643b11
CSV.cpp
Go to the documentation of this file.
1 /*
2  * This is free software: you can redistribute it and/or modify it
3  * under the terms of the GNU General Public License as published by
4  * the Free Software Foundation, either version 3 of the License, or
5  * any later version.
6  * The software is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  * You should have received a copy of the GNU General Public License
11  * along with the software. If not, see <http://www.gnu.org/licenses/>.
12  *
13  * Copyright 2017, Kuylen E, Willem L, Broeckhove J
14  */
15 
21 #include "CSV.h"
22 
23 #include <fstream>
24 
25 using namespace std;
26 
27 namespace {
28 
34 const filesys::path check(const filesys::path& filename, const filesys::path& root = filesys::current_path())
35 {
36  const filesys::path file_path = canonical(absolute(root / filename));
37  if (!is_regular_file(file_path)) {
38  throw runtime_error(string(__func__) + ">File " + file_path.string() + " not present. Aborting.");
39  }
40  return file_path;
41 }
42 
43 } // namespace
44 
45 namespace stride {
46 namespace util {
47 
48 CSV::CSV(const filesys::path& path, std::initializer_list<std::string> optLabels) : m_labels(), m_column_count(0)
49 {
50  try {
51  filesys::path full_path = check(path);
52  std::ifstream file;
53  file.open(full_path.string());
54  if (!file.is_open()) {
55  throw runtime_error("Error opening csv file: " + full_path.string());
56  }
57 
58  ReadFromStream(file);
59  } catch (std::runtime_error& error) {
60  // thrown by util::checkFile
61  if (optLabels.size() == 0) {
62  throw error;
63  } else {
64  m_labels = optLabels;
65  m_column_count = m_labels.size();
66  }
67  }
68 }
69 
70 CSV::CSV(std::istream& inputStream) : m_labels(), m_column_count(0) { ReadFromStream(inputStream); }
71 
72 CSV::CSV(const vector<string>& labels) : m_labels(labels), m_column_count(labels.size()) {}
73 
74 CSV::CSV(size_t columnCount) : m_labels(), m_column_count(columnCount)
75 {
76  for (unsigned i = 1U; i < columnCount + 1; ++i) {
77  m_labels.emplace_back(ToString(i));
78  }
79 }
80 
81 void CSV::AddRows(const vector<vector<string>>& rows)
82 {
83  for (const vector<string>& row : rows) {
84  AddRow(row);
85  }
86 }
87 
88 bool CSV::operator==(const CSV& other) const
89 {
90  return m_labels == other.m_labels && (const vector<CSVRow>&)*this == (const vector<CSVRow>&)other;
91 }
92 
93 size_t CSV::GetIndexForLabel(const string& label) const
94 {
95  for (unsigned int index = 0; index < m_labels.size(); ++index) {
96  if (m_labels.at(index) == label)
97  return index;
98  }
99  throw runtime_error("Label: " + label + " not found in CSV");
100 }
101 
102 void CSV::Write(const filesys::path& path) const
103 {
104  std::ofstream file;
105  file.open(path.string());
106  if (!file.is_open()) {
107  throw runtime_error("Error opening csv file: " + path.string());
108  }
109  file << *this;
110  file.close();
111 }
112 
113 void CSV::WriteLabels(std::ofstream& file) const
114 {
115  for (unsigned int i = 0; i < m_labels.size(); ++i) {
116  const string& label = m_labels.at(i);
117  file << "\"" << label << "\"";
118  if (i != m_labels.size() - 1) {
119  file << ",";
120  } else {
121  file << endl;
122  }
123  }
124 }
125 
126 void CSV::WriteRows(std::ofstream& file) const
127 {
128  for (const CSVRow& row : *this) {
129  file << row << endl;
130  }
131 }
132 
133 void CSV::ReadFromStream(std::istream& inputStream)
134 {
135  std::string line;
136 
137  // header
138  getline(inputStream, line);
139  line = Trim(line);
140  std::vector<std::string> headerLabels = Split(line, ","); // Split is bad! There is no option to escape ",".
141  for (const std::string& label : headerLabels) {
142  m_labels.push_back(Trim(label, "\""));
143  }
144  m_column_count = m_labels.size();
145 
146  // body
147  while (getline(inputStream, line)) {
148  line = Trim(line);
149  if (!line.empty()) {
150  std::vector<std::string> values =
151  Split(line, ","); // Split is bad! There is no option to escape ",".
152  AddRow(values);
153  }
154  }
155 }
156 
157 void CSV::AddRow(const vector<string>& values)
158 {
159  CSVRow csvRow(this, values);
160  this->push_back(csvRow);
161 }
162 
163 const std::vector<std::string>& CSV::GetLabels() const { return m_labels; }
164 
165 } // namespace util
166 } // namespace stride
void WriteLabels(std::ofstream &file) const
Write header with labels.
Definition: CSV.cpp:113
Row in CSV file.
Definition: CSVRow.h:36
std::string ToString(const T &value)
Builds a string representation of a value of type T.
Definition: StringUtils.h:90
const std::vector< std::string > & GetLabels() const
Definition: CSV.cpp:163
bool operator==(const CSV &other) const
Comparison operator.
Definition: CSV.cpp:88
void Write(const filesys::path &path) const
Write CSV to file.
Definition: CSV.cpp:102
void ReadFromStream(std::istream &inputStream)
Read data from input stream.
Definition: CSV.cpp:133
size_t m_column_count
Definition: CSV.h:125
size_t GetIndexForLabel(const std::string &label) const
Convert label to index for more user friendly and robust implementation.
Definition: CSV.cpp:93
std::vector< std::string > m_labels
Definition: CSV.h:124
void AddRows(const std::vector< std::vector< std::string >> &rows)
Add multiple rows of strings at the same time.
Definition: CSV.cpp:81
STL namespace.
std::vector< std::string > Split(const std::string &s, const std::string &delimiters)
Split a string (in order of occurence) by splitting it on the given delimiters.
Definition: StringUtils.h:58
CSV()=default
Default constructor, used for swig.
std::string Trim(const std::string &source, const std::string &t=" ")
Trim characters at both ends of string.
Definition: StringUtils.h:167
void WriteRows(std::ofstream &file) const
Write the body of rows.
Definition: CSV.cpp:126
A collection of CSVRow elements.
Definition: CSV.h:46
void AddRow(const T &...values)
Add row of values.
Definition: CSV.h:129
Namespace for the simulator and related classes.
Definition: Calendar.cpp:28
Header file of base class for config that needs to be read from a file.