Euphoria
table.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 #include "assert/assert.h"
5 #include "base/numeric.h"
6 #include "base/rect.h"
7 #include "base/cint.h"
8 #include "base/vec2.h"
9 
10 namespace eu::core
11 {
12  // NewCol function??? probably less useful than insert functions
13  // todo(Gustav): add insert before/after row/col
14  // todo(Gustav): add remove row/col
15 
16  template <typename T>
17  struct Table
18  {
19  using Idx = int;
20 
21  Table() = default;
22 
23  [[nodiscard]] static Table from_width_height(Idx width, Idx height, T d = T())
24  {
25  return Table(width, height, d);
26  }
27 
28  [[nodiscard]] static Table from_height_width(Idx height, Idx width, T d = T())
29  {
30  return Table(width, height, d);
31  }
32 
33  void add_row(T d = T())
34  {
35  ASSERT(width > 0);
36  data.resize(data.size() + width, d);
37  height += 1;
38  }
39 
40  void clear(T d = T())
41  {
42  for(size_t index = 0; index < data.size(); index += 1)
43  {
44  data[index] = d;
45  }
46  }
47 
48  template <typename TFunc>
49  void set_all(TFunc f)
50  {
51  for(Idx y = 0; y < height; y += 1)
52  {
53  for(Idx x = 0; x < width; x += 1)
54  {
55  (*this)[{x, y}] = f(x, y);
56  }
57  }
58  }
59 
66  void add_row(const std::vector<T>& row, T d = T())
67  {
68  // do nothing on empty rows
69  if(row.empty())
70  {
71  return;
72  }
73 
74  if(width == 0)
75  {
76  // this is a new table, the row is the new table
77  ASSERTX(height == 0, height);
78  data = row;
79  width = c_sizet_to_int(row.size());
80  height = 1;
81  }
82  else if(width == conv(row.size()))
83  {
84  // the number of columns math the new new, just insert it
85  data.insert(data.end(), row.begin(), row.end());
86  height += 1;
87  }
88  else if(width > conv(row.size()))
89  {
90  // new row has less columns than the table, solve by expanding the new row with empties
91  data.insert(data.end(), row.begin(), row.end());
92  for(auto col = conv(row.size()); col < width; col += 1)
93  {
94  data.push_back(d);
95  }
96  height += 1;
97  }
98  else
99  {
100  // new row has more columns, solve by expanding table with empties
101  ASSERTX(width < conv(row.size()), width, row.size());
102  expand_width(c_sizet_to_int(row.size()), d);
103  data.insert(data.end(), row.begin(), row.end());
104  height += 1;
105  }
106  }
107 
113  void expand_width(Idx new_width, T d = T())
114  {
115  // todo(Gustav): only insert the columns we need
116  ASSERT(width != 0);
117  ASSERTX(width < new_width, width, new_width);
118 
119  auto t = Table<T>::from_width_height(new_width, height, d);
120  for(Idx x = 0; x < width; x += 1)
121  {
122  for(Idx y = 0; y < height; y += 1)
123  {
124  t[{x, y}] = (*this)[{x, y}];
125  }
126  }
127  *this = t;
128  }
129 
130 
131  [[nodiscard]] bool is_inside(Idx x, Idx y) const
132  {
133  return get_indices().contains_inclusive(x, y);
134  }
135 
136  [[nodiscard]] size_t get_data_index(const vec2i& pos) const
137  {
138  ASSERTX
139  (
140  is_within_inclusive_as_int(0, pos.x, width - 1) && is_within_inclusive_as_int(0, pos.y, height - 1),
141  pos.x, width,
142  pos.y, height
143  );
144  return pos.y * width + pos.x;
145  }
146 
147 
148  [[nodiscard]] Recti get_indices() const
149  {
150  return Recti::from_width_height(width - 1, height - 1);
151  }
152 
153  [[nodiscard]] Idx get_width() const
154  {
155  return width;
156  }
157 
158  [[nodiscard]] Idx get_height() const
159  {
160  return height;
161  }
162 
163 
164 
165  T operator[](const vec2i& pos) const
166  {
167  const auto index = get_data_index(pos);
168  ASSERTX(index < data.size(), index, data.size());
169  return data[index];
170  }
171 
172  typename std::vector<T>::reference operator[](const vec2i& pos)
173  {
174  const auto index = get_data_index(pos);
175  ASSERTX(index < data.size(), index, data.size());
176  return data[index];
177  }
178 
179 
180  [[nodiscard]] static constexpr Idx
181  conv(size_t t)
182  {
183  return c_sizet_to_int(t);
184  }
185 
186  private:
187  // table is stored in in place like [row, row, ...row]
188  std::vector<T> data;
189  Idx width = 0;
190  Idx height = 0;
191 
192 
193  Table(Idx c, Idx r, T d = T()) : data(c * r, d), width(c), height(r)
194  {
195  ASSERTX(width >= 0 && height >= 0, width, height);
196  }
197  };
198 
199  template <typename T>
200  std::vector<T> calc_column_as_vector(const Table<T>& t, typename Table<T>::Idx x)
201  {
202  ASSERTX(x < t.get_width(), x, t.get_width());
203  std::vector<T> r;
204  r.reserve(t.get_height());
205  for(typename Table<T>::Idx y = 0; y < t.get_height(); ++y)
206  {
207  r.emplace_back(t[{x, y}]);
208  }
209  return r;
210  }
211 
212  template <typename T>
213  std::vector<T> calc_row_as_vector(const Table<T>& t, typename Table<T>::Idx y)
214  {
215  ASSERTX(y < t.get_height(), y, t.get_height());
216 
217  std::vector<T> r;
218  r.reserve(t.get_width());
219  for(typename Table<T>::Idx x = 0; x < t.get_width(); ++x)
220  {
221  r.emplace_back(t[{x, y}]);
222  }
223  return r;
224  }
225 
226 }
#define ASSERTX(x,...)
Definition: assert.h:48
#define ASSERT(x)
Definition: assert.h:29
std::vector< T > calc_column_as_vector(const Table< T > &t, typename Table< T >::Idx x)
Definition: table.h:200
std::vector< T > calc_row_as_vector(const Table< T > &t, typename Table< T >::Idx y)
Definition: table.h:213
int c_sizet_to_int(size_t t)
Definition: cint.cc:11
bool is_within_inclusive_as_int(int min, int c, int max)
Definition: numeric.cc:116
bool contains_inclusive(const vec2i &p) const
Definition: rect.cc:689
static Recti from_width_height(int width, int height)
Definition: rect.cc:573
T operator[](const vec2i &pos) const
Definition: table.h:165
void set_all(TFunc f)
Definition: table.h:49
static Table from_height_width(Idx height, Idx width, T d=T())
Definition: table.h:28
Idx get_height() const
Definition: table.h:158
Idx get_width() const
Definition: table.h:153
size_t get_data_index(const vec2i &pos) const
Definition: table.h:136
static constexpr Idx conv(size_t t)
Definition: table.h:181
bool is_inside(Idx x, Idx y) const
Definition: table.h:131
static Table from_width_height(Idx width, Idx height, T d=T())
Definition: table.h:23
Table()=default
void add_row(const std::vector< T > &row, T d=T())
Add a new row to the table.
Definition: table.h:66
Recti get_indices() const
Definition: table.h:148
void add_row(T d=T())
Definition: table.h:33
void clear(T d=T())
Definition: table.h:40
void expand_width(Idx new_width, T d=T())
Expand the table to the new width.
Definition: table.h:113
std::vector< T >::reference operator[](const vec2i &pos)
Definition: table.h:172
Definition: vec2.h:72
int y
Definition: vec2.h:74
int x
Definition: vec2.h:73