gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
a Global And Modular Bsm Inference Tool
table_formatter.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
18 
19 #include <cstdlib>
20 #include <sstream>
21 #include <iomanip>
22 #include <map>
23 #include <utility>
27 
28 namespace Gambit
29 {
30  /********************************************/
31  /****** table formatter output funcs ********/
32  /********************************************/
33 
34  inline void wrap_lines (std::vector<std::vector<std::string>> &data_in, const std::vector<int> &widths, const std::vector<int> &minWidths, double pad, std::vector<unsigned char> *row_flags = 0)
35  {
36  std::vector<unsigned char>::iterator f_it;
37  if (row_flags)
38  f_it= row_flags->begin();
39  for (auto it = data_in.begin(), end = data_in.end(); it != end;)
40  {
41  int col_num = it->size();
42  std::vector<std::string> temp(col_num, "");
43  bool wrapped = false;
44  for (int i = 0; i < col_num; i++)
45  {
46  if (minWidths.at(i) > 0)
47  {
48  int w = widths[i];
49  if (i != col_num-1)
50  {
51  w -= pad;
52  }
53  if (minWidths.at(i) > w)
54  {
55  w = minWidths.at(i);
56  }
57  if (w < (int)(*it)[i].length())
58  {
59  std::string sub = (*it)[i];
60  auto pos = sub.find_first_not_of(" ");
61  if (pos != std::string::npos)
62  {
63  (*it)[i] = separate_line(sub, pos, w);
64  temp[i] = sub;
65  wrapped = true;
66  }
67  else
68  {
69  (*it)[i] = "";
70  }
71  }
72  }
73  }
74 
75  ++it;
76 
77  if (wrapped)
78  {
79  if (row_flags)
80  f_it = row_flags->insert(f_it, 0x80);
81  it = data_in.insert(it, temp);
82  end = data_in.end();
83  }
84 
85  if (row_flags)
86  ++f_it;
87  }
88  }
89 
90  std::string table_formatter::str()
91  {
92  int cols_screen = get_screen_cols();
93  int cols_tot = 0;
94  int row_num = data.size();
95  int col_last = col_num - 1;
96  int row_last = row_num - 1;
97  std::vector<int> col_sizes;
98  std::stringstream out;
99  bool overflow = false;
100 
101  if (cols_screen > 0)
102  {
103  col_sizes = std::vector<int>(col_num, (cols_screen)/col_num);
104  col_sizes[col_last] += cols_screen%col_num;
105  }
106  else
107  {
108  col_sizes = defaultWidths;
109  }
110 
111  if (wrap)
112  {
113  wrap_lines (data, col_sizes, minWidths, pad, &row_flags);
114  wrap_lines (titles, col_sizes, minWidths, pad);
115  }
116 
117  std::vector<int> max_col(col_num, 0);
118 
119  for (auto it = titles.begin(), end = titles.end(); it != end; ++it)
120  {
121  for (int i = 0; i < col_num; i++)
122  {
123  if ((unsigned int)max_col[i] < (*it)[i].length())
124  max_col[i] = (*it)[i].length();
125  }
126  }
127 
128  for (auto it = data.begin(), end = data.end(); it != end; ++it)
129  {
130  for (int i = 0; i < col_num; i++)
131  {
132  if ((*it)[i].length() > (unsigned int)(max_col[i]))
133  max_col[i] = (*it)[i].length();
134 
135  }
136  }
137 
138  if (pad > 0) for (int i = 0; i < col_last; i++)
139  {
140  max_col[i] += pad;
141  }
142 
143  for (int i = 0; i < col_last; i++)
144  {
145  if (col_sizes[i] < max_col[i])
146  {
147  col_sizes[i+1] -= (max_col[i] - col_sizes[i]);
148  col_sizes[i] = max_col[i];
149  }
150  }
151 
152  if (col_num > 1)
153  {
154  if (col_sizes[col_last] < max_col[col_last])
155  {
156  int diff = max_col[col_last] - col_sizes[col_last];
157  bool changed = true;
158  while (diff > 0 && changed)
159  {
160  changed = false;
161  for (int i = 0; i < col_last; i++)
162  {
163  if (col_sizes[i] > max_col[i] && diff > 0)
164  {
165  col_sizes[col_last]++;
166  col_sizes[i]--;
167  diff--;
168  changed = true;
169  }
170  }
171  }
172 
173  if (diff > 0)
174  {
175  col_sizes[col_last] = max_col[col_last];
176  overflow = true;
177  }
178  }
179  }
180 
181  std::string spaces(pad, ' ');
182 
183  std::vector<std::ios_base::fmtflags> ff(col_num);
184  for (int i = 0; i < col_num; i++)
185  {
186  if (col_flags[i] & JUST_RIGHT)
187  {
188  ff[i] = std::ios::right;
189  }
190  else if (col_flags[i] & JUST_CENTER)
191  {
192  ff[i] = std::ios::left;
193  }
194  else
195  {
196  ff[i] = std::ios::left;
197  }
198 
199  cols_tot += col_sizes[i];
200  }
201 
202  if (pad > 0) for (int i = 0; i < col_last; i++)
203  {
204  col_sizes[i] -= pad;
205  }
206 
207  if (overflow && cols_screen > 0)
208  out << "\x1b[33;01m" << std::setw(cols_screen) << ">>> more here >>>" << "\x1b[0m" << std::endl;
209 
210  if(top)
211  {
212  out << "\x1b[01m\x1b[04m" << std::setw(cols_tot) << "" << "\x1b[0m";
213  }
214  out << std::endl;
215 
216  for (auto it = titles.begin(), end = titles.end(); it != end; ++it)
217  {
218  if (it == end - 1)
219  {
220  out << "\x1b[01m\x1b[04m";
221  }
222  else
223  {
224  out << "\x1b[01m";
225  }
226  for (int i = 0; i < col_num; i++)
227  {
228  out << std::setiosflags(ff[i]);
229  if (col_flags[i] & JUST_CENTER)
230  out << std::setw(col_sizes[i]) << std::string((col_sizes[i]-it->size())/2, ' ') + (*it)[i];
231  else
232  out << std::setw(col_sizes[i]) << (*it)[i];
233  out << std::resetiosflags(ff[i]);
234 
235  if (i < col_last)
236  out << spaces;
237  }
238  out << "\x1b[0m" << std::endl;
239  }
240 
241  out << std::endl;
242 
243  for (int i = 0; i < row_num; i++)
244  {
245  if (bottom && i == row_last && bool(row_flags[i] & WRAP))
246  {
247  out << "\x1b[01m\x1b[04m";
248  }
249  else
250  {
251  out << "\x1b[0m";
252  }
253 
254  for (int j = 0; j < col_num; j++)
255  {
256  std::pair<int, int> key(i, j);
257  if (flags.find(key) == flags.end())
258  {
259  out << std::setiosflags(ff[j]);
260  if (col_flags[j] & JUST_CENTER)
261  out << std::setw(col_sizes[j]) << std::string((col_sizes[j]-data[i][j].size())/2, ' ') + data[i][j];
262  else
263  out << std::setw(col_sizes[j]) << data[i][j];
264  out << std::resetiosflags(ff[j]);
265  }
266  else
267  {
268  out << std::setiosflags(ff[j]);
269  if (flags[key] & RED)
270  {
271  out << "\x1b[31;01m";
272  }
273  if (flags[key] & GREEN)
274  {
275  out << "\x1b[32;01m";
276  }
277  if (flags[key] & YELLOW)
278  {
279  out << "\x1b[33;01m";
280  }
281  if (flags[key] & BOLD)
282  {
283  out << "\x1b[01m";
284  }
285  if (flags[key] & UNDERLINE)
286  {
287  out << "\x1b[04m";
288  }
289  if (col_flags[j] & JUST_CENTER)
290  {
291  out << std::setw(col_sizes[j]) << std::string((col_sizes[j]-data[i][j].size())/2, ' ') + data[i][j];
292  }
293  else
294  {
295  out << std::setw(col_sizes[j]) << data[i][j];
296  }
297  out << "\x1b[0m";
298  out << std::resetiosflags(ff[j]);
299  }
300 
301  if (j < col_last)
302  out << spaces;
303  }
304 
305  if (bool(row_flags[i] & WRAP))
306  {
307  if (bottom && i == row_last)
308  {
309  out << "\x1b[0m";
310  }
311  out << std::endl;
312  }
313  else
314  {
315  out << "\n";
316  if (bottom && i == row_last)
317  {
318  out << "\x1b[01m\x1b[04m" << std::setw(cols_tot) << "" << "\x1b[0m";
319  }
320  out << std::endl;
321  }
322  }
323 
324  out << std::flush;
325 
326  return out.str();
327  }
328 
329 }
std::map< std::pair< int, int >, unsigned char > flags
static const unsigned char UNDERLINE
static const unsigned char GREEN
int get_screen_cols()
Utility Functions for the Gambit Scanner.
static const unsigned char JUST_CENTER
std::string separate_line(std::string &line, std::string::size_type indent, std::string::size_type cols_pos)
std::vector< int > defaultWidths
void wrap_lines(std::vector< std::vector< std::string >> &data_in, const std::vector< int > &widths, const std::vector< int > &minWidths, double pad, std::vector< unsigned char > *row_flags=0)
static const unsigned char BOLD
static const unsigned char JUST_RIGHT
static const unsigned char RED
std::vector< std::vector< std::string > > data
Variadic utilty functions.
DS5_MSPCTM DS_INTDOF int
Utility Functions for the Gambit Scanner.
std::vector< int > minWidths
std::vector< unsigned char > col_flags
static const unsigned char WRAP
std::vector< unsigned char > row_flags
static const unsigned char YELLOW
std::vector< std::vector< std::string > > titles
TODO: see if we can use this one:
Definition: Analysis.hpp:33