Euphoria
table_string.cc
Go to the documentation of this file.
1 #include "core/table_string.h"
2 
3 #include <algorithm>
4 
5 #include "base/stringutils.h"
6 #include "base/cint.h"
7 #include "base/stringbuilder.h"
8 
9 
10 namespace eu::core
11 {
12 
13 
15 parse_csv(const std::string& csv_data, const CsvParserOptions& options)
16 {
17  const auto add_row_to_table =
18  [](StringTable* table, const std::vector<std::string>& row)
19  {
20  if(row.empty()) { return; }
21  table->add_row(row);
22  };
23  auto file = TextfileParser::from_string(csv_data);
24 
25  StringTable table;
26 
27  std::vector<std::string> row;
28  auto ss = StringBuilder{};
29  bool inside_string = false;
30  bool added = false;
31  bool was_from_string = false;
32 
33  while(file.has_more())
34  {
35  const auto c = file.read_char();
36  if(inside_string)
37  {
38  if(c == options.str)
39  {
40  if(file.peek_char() == options.str)
41  {
42  ss.add_char(c);
43  file.read_char();
44  }
45  else
46  {
47  inside_string = false;
48  }
49  }
50  else
51  {
52  ss.add_char(c);
53  }
54  }
55  else
56  {
57  if(c == options.str)
58  {
59  if(added)
60  {
61  // todo(Gustav): generate error if string contains stuff other than whitespace
62  ss.clear();
63  }
64  inside_string = true;
65  was_from_string = true;
66  added = true;
67  }
68  else if(c == options.delim)
69  {
70  auto column_data = ss.to_string();
71  if(!was_from_string && options.trim == CsvTrim::trim)
72  {
73  column_data = trim(column_data);
74  }
75  row.push_back(column_data);
76  ss.clear();
77  added = false;
78  was_from_string = false;
79  }
80  else if(c == '\n')
81  {
82  if(added)
83  {
84  auto column_data = ss.to_string();
85  if(!was_from_string && options.trim == CsvTrim::trim)
86  {
87  column_data = trim(column_data);
88  }
89  row.push_back(column_data);
90  }
91  ss.clear();
92  add_row_to_table(&table, row);
93  row.resize(0);
94  added = false;
95  was_from_string = false;
96  }
97  else
98  {
99  if(was_from_string)
100  {
101  // skip
102  // todo(Gustav): error on non whitespace?
103  }
104  else
105  {
106  ss.add_char(c);
107  added = true;
108  }
109  }
110  }
111  }
112 
113  if(added)
114  {
115  auto column_data = ss.to_string();
116  if(!was_from_string && options.trim == CsvTrim::trim)
117  {
118  column_data = trim(column_data);
119  }
120  row.push_back(column_data);
121  }
122  add_row_to_table(&table, row);
123 
124  return table;
125 }
126 
127 int
128 calc_width_of_string(const std::string& t)
129 {
130  // todo(Gustav): bugfix longstring\nshort will return length of short, not longstring
131  int w = 0;
132 
133  for(auto c: t)
134  {
135  if(c == '\n')
136  {
137  w = 0;
138  }
139  else
140  {
141  w += 1;
142  }
143  }
144 
145  return w;
146 }
147 
148 int
149 calc_height_of_string(const std::string& t)
150 {
151  int h = 1;
152  for(auto c: t)
153  {
154  if(c == '\n')
155  {
156  h += 1;
157  }
158  }
159  return h;
160 }
161 
162 int
164 {
165  int width = 0;
166  for(StringTable::Idx y = 0; y < t.get_height(); y += 1)
167  {
168  width = std::max<int>(width, calc_width_of_string(t[{c, y}]));
169  }
170  return width;
171 }
172 
173 int
175 {
176  int height = 0;
177  for(StringTable::Idx x = 0; x < t.get_width(); x += 1)
178  {
179  height = std::max<int>(height, calc_height_of_string(t[{x, r}]));
180  }
181  return height;
182 }
183 
184 std::vector<int>
185 calc_all_column_widths(const StringTable& table, int extra)
186 {
187  const auto number_of_cols = table.get_width();
188  std::vector<int> sizes(number_of_cols);
189  for(StringTable::Idx column_index = 0; column_index < number_of_cols; column_index += 1)
190  {
191  sizes[column_index] = calc_single_column_width(table, column_index) + extra;
192  }
193  return sizes;
194 }
195 
199 {
201  table.get_width(), calc_single_row_height(table, row));
202  for(int column_index = 0; column_index < table.get_width(); column_index += 1)
203  {
204  const auto rows = split(table[{column_index, row}], '\n');
205  for(StringTable::Idx row_index = 0; row_index < StringTable::conv(rows.size()); row_index += 1)
206  {
207  ret[{column_index, row_index}] = rows[row_index];
208  }
209  }
210  return ret;
211 }
212 
213 void
214 print_table_simple(std::ostream& out, const StringTable& maintable)
215 {
216  // todo(Gustav): cleanup this function...
217  const auto begin_str_padding = 1;
218  const auto end_space_padding = 3;
219 
220  const auto begin_str = std::string(begin_str_padding, ' ');
221  const auto end_str = std::string(end_space_padding, ' ');
222  const auto number_of_cols = maintable.get_width();
223  const auto number_of_rows = maintable.get_height();
224 
225  const std::vector<int> sizes = calc_all_column_widths(maintable, 1);
226 
227  const auto total_padding = begin_str_padding + end_space_padding;
228 
229  for(StringTable::Idx mainrow = 0; mainrow < number_of_rows; ++mainrow)
230  {
231  const auto subtable = split_table_cells_on_newline(maintable, mainrow);
232  for(StringTable::Idx subrow = 0; subrow < subtable.get_height(); ++subrow)
233  {
234  for(StringTable::Idx col = 0; col < number_of_cols; ++col)
235  {
236  const auto cell = begin_str + subtable[{col, subrow}];
237  auto line_length = c_sizet_to_int(cell.length());
238  out << cell;
239 
240  if(col != number_of_cols - 1)
241  {
242  for(StringTable::Idx padding_counter = line_length;
243  padding_counter < sizes[col] + total_padding;
244  ++padding_counter)
245  {
246  out << ' ';
247  }
248  }
249  }
250  out << '\n';
251 
252  if(mainrow == 0)
253  {
254  for(StringTable::Idx col = 0; col < number_of_cols; ++col)
255  {
256  const auto row_text
257  = std::string(
258  sizes[col] + begin_str_padding, '-')
259  + std::string(end_space_padding, ' ');
260  out << row_text;
261  }
262  out << '\n';
263  }
264  }
265  }
266 }
267 
268 void
269 print_table_grid(std::ostream& out, const StringTable& maintable)
270 {
271  const std::vector<int> sizes = calc_all_column_widths(maintable, 0);
272 
273  // prefer enum since vs2017 requires one to capture constexpr (weird I know)
274  enum
275  {
276  internal_space = 1
277  };
278 
279  auto some_space = [&out](int spaces, char c = ' ') {
280  for(int space_counter = 0; space_counter < spaces; space_counter += 1)
281  {
282  out << c;
283  }
284  };
285 
286  auto horizontal_line = [&some_space, &out, &sizes]() {
287  out << '+';
288  for(auto s: sizes)
289  {
290  some_space(s + internal_space * 2, '-');
291  out << '+';
292  }
293  out << '\n';
294  };
295 
296  horizontal_line();
297 
298  for(StringTable::Idx y = 0; y < maintable.get_height(); ++y)
299  {
300  const auto subtable = split_table_cells_on_newline(maintable, y);
301  for(StringTable::Idx suby = 0; suby < subtable.get_height(); suby += 1)
302  {
303  out << "|";
304  for(StringTable::Idx x = 0; x < subtable.get_width(); ++x)
305  {
306  const auto cell = subtable[{x, suby}];
307  some_space(internal_space);
308  out << cell;
309  some_space(sizes[x] - c_sizet_to_int(cell.length()));
310  some_space(internal_space);
311  out << '|';
312  }
313  out << '\n';
314  }
315 
316  if(y == 0)
317  {
318  horizontal_line();
319  }
320  }
321 
322  horizontal_line();
323 }
324 
325 
326 
327 }
std::vector< std::string > split(const std::string &s, char delim)
Definition: stringutils.cc:431
std::string trim(const std::string &string_to_trim, std::string_view trim_characters)
Remove characters from both the start and the end.
Definition: stringutils.cc:79
void print_table_grid(std::ostream &out, const StringTable &maintable)
std::vector< int > calc_all_column_widths(const StringTable &table, int extra)
int calc_width_of_string(const std::string &t)
int calc_single_row_height(const StringTable &t, int r)
void print_table_simple(std::ostream &out, const StringTable &maintable)
StringTable split_table_cells_on_newline(const StringTable &table, StringTable::Idx row)
Return a new table based on row, where each cell is split at newline over many rows.
int calc_single_column_width(const StringTable &t, int c)
StringTable parse_csv(const std::string &csv_data, const CsvParserOptions &options)
Definition: table_string.cc:15
int calc_height_of_string(const std::string &t)
Table< std::string > StringTable
Definition: table_string.h:16
int c_sizet_to_int(size_t t)
Definition: cint.cc:11
String utility functions.
Idx get_height() const
Definition: table.h:158
Idx get_width() const
Definition: table.h:153
static constexpr Idx conv(size_t t)
Definition: table.h:181
static Table from_width_height(Idx width, Idx height, T d=T())
Definition: table.h:23
void add_row(T d=T())
Definition: table.h:33
static TextfileParser from_string(const std::string &str)