User Guide
table_data.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <cassert>
9 #include <iostream>
10 #include <numeric>
11 
12 #include "utils/string_utils.hpp"
13 #include "utils/table_data.hpp"
14 
15 namespace nmodl {
16 namespace utils {
17 
18 /**
19  * Print table data in below shown format: title as first row (centrally aligned),
20  * second row is header for individual column (centrally aligned) and then all data
21  * rows (with associated alignments).
22  *
23  * ----------------------------------------------------------------------------------------
24  * | mBetaf [FunctionBlock IN NMODL_GLOBAL] POSITION : 109.1-8 SCOPE : LOCAL |
25  * ----------------------------------------------------------------------------------------
26  * | NAME | PROPERTIES | LOCATION | # READS | # WRITES |
27  * ----------------------------------------------------------------------------------------
28  * | v | argument | 109.17 | 0 | 0 |
29  * ----------------------------------------------------------------------------------------
30  */
31 
32 void TableData::print(std::ostream& stream, int indent) const {
33  constexpr std::size_t PADDING{1};
34 
35  /// not necessary to print empty table
36  if (rows.empty() || headers.empty()) {
37  return;
38  }
39 
40  /// based on indentation level, spaces to prefix
41  assert(indent >= 0);
42  auto gutter = std::string(static_cast<std::size_t>(indent) * 4, ' ');
43 
44  auto const ncolumns = headers.size();
45  std::vector<std::size_t> col_width(ncolumns);
46 
47  /// alignment is optional, so fill remaining with right alignment
48  auto all_alignments = alignments;
49  all_alignments.reserve(ncolumns);
50  for (unsigned i = alignments.size(); i < ncolumns; i++) {
51  all_alignments.push_back(stringutils::text_alignment::center);
52  }
53 
54  /// calculate space required for each column
55  std::size_t row_width{};
56  for (unsigned i = 0; i < headers.size(); i++) {
57  col_width[i] = headers[i].length() + PADDING;
58  row_width += col_width[i];
59  }
60 
61  /// if title is larger than headers then every column
62  /// width needs to be scaled
63  if (title.length() > row_width) {
64  auto const extra_size = title.length() - row_width;
65  auto column_pad = extra_size / ncolumns;
66  if ((extra_size % ncolumns) != 0) {
67  column_pad++;
68  }
69  for (auto& column: col_width) {
70  column += column_pad;
71  }
72  }
73 
74  /// check length of columns in each row to find max length required
75  for (const auto& row: rows) {
76  for (unsigned i = 0; i < row.size(); i++) {
77  if (col_width[i] < (row[i].length()) + PADDING) {
78  col_width[i] = row[i].length() + PADDING;
79  }
80  }
81  }
82 
83  std::stringstream header;
84  header << "| ";
85  for (size_t i = 0; i < headers.size(); i++) {
86  assert(col_width[i] <= std::numeric_limits<int>::max());
87  auto text = stringutils::align_text(headers[i],
88  static_cast<int>(col_width[i]),
90  header << text << " | ";
91  }
92 
93  row_width = header.str().length();
94  auto separator_line = std::string(row_width - 1, '-');
95 
96  /// title row
97  if (!title.empty()) {
98  assert(row_width >= 3 && row_width - 3 <= std::numeric_limits<int>::max());
99  auto fmt_title = stringutils::align_text(title,
100  static_cast<int>(row_width - 3),
102  stream << '\n' << gutter << separator_line;
103  stream << '\n' << gutter << '|' << fmt_title << '|';
104  }
105 
106  /// header row
107  stream << '\n' << gutter << separator_line;
108  stream << '\n' << gutter << header.str();
109  stream << '\n' << gutter << separator_line;
110 
111  /// data rows
112  for (const auto& row: rows) {
113  stream << '\n' << gutter << "| ";
114  for (unsigned i = 0; i < row.size(); i++) {
115  assert(col_width[i] <= std::numeric_limits<int>::max());
116  stream << stringutils::align_text(row[i],
117  static_cast<int>(col_width[i]),
118  all_alignments[i])
119  << " | ";
120  }
121  }
122 
123  /// bottom separator line
124  stream << '\n' << gutter << separator_line << '\n';
125 }
126 
127 void TableData::print(int indent) const {
128  print(std::cout, indent);
129 }
130 
131 } // namespace utils
132 } // namespace nmodl
nmodl::utils::TableData::title
std::string title
title of the table
Definition: table_data.hpp:40
nmodl::utils::TableData::rows
std::vector< TableRowType > rows
data
Definition: table_data.hpp:46
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::utils::TableData::alignments
std::vector< stringutils::text_alignment > alignments
alignment for every column of data rows
Definition: table_data.hpp:49
string_utils.hpp
Implement string manipulation functions.
nmodl::stringutils::align_text
static std::string align_text(const std::string &text, int width, text_alignment type)
Aligns a text within a field of width width.
Definition: string_utils.hpp:167
nmodl::stringutils::text_alignment::center
@ center
table_data.hpp
Implement generic table data structure.
nmodl::utils::TableData::headers
TableRowType headers
top header/keys
Definition: table_data.hpp:43
nmodl::utils::TableData::print
void print(int indent=0) const
Definition: table_data.cpp:127