Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
tabulate.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
21#include "shambase/string.hpp"
22#include <cstddef>
23#include <stdexcept>
24#include <string>
25#include <variant>
26#include <vector>
27
28namespace shambase {
29
30 struct table {
31
32 size_t cols_count;
33 table(size_t column_count) : cols_count(column_count) {}
34
35 struct rule {};
36 struct double_rule {};
37 struct rulled_data {
38 std::vector<std::string> colnames;
39 };
40 enum positionning {
41 left,
42 right,
43 center,
44 };
45 struct data {
46 std::vector<std::string> cols;
47 positionning position;
48 };
49
50 std::vector<std::variant<rule, double_rule, rulled_data, data>> table_lines;
51
52 void add_rule() { table_lines.push_back(rule{}); }
53 void add_double_rule() { table_lines.push_back(double_rule{}); }
54 void add_rulled_data(const std::vector<std::string> &colnames) {
55 if (colnames.size() != cols_count) {
57 "the number of column does not match colnames.size() != cols_count ({} != {})",
58 colnames.size(),
59 cols_count));
60 }
61 table_lines.push_back(rulled_data{colnames});
62 }
63 void add_data(const std::vector<std::string> &cols, positionning position) {
64 if (cols.size() != cols_count) {
66 "the number of column does not match cols.size() != cols_count ({} != {})",
67 cols.size(),
68 cols_count));
69 }
70 table_lines.push_back(data{cols, position});
71 }
72
73 std::vector<size_t> compute_widths() {
74 std::vector<size_t> widths(cols_count);
75 for (auto &line : table_lines) {
76 if (data *data_line = std::get_if<data>(&line)) {
77 for (u32 i = 0; i < cols_count; i++) {
78 widths[i] = std::max(widths[i], data_line->cols[i].size());
79 }
80 } else if (rulled_data *head_and_ruller_line = std::get_if<rulled_data>(&line)) {
81 for (u32 i = 0; i < cols_count; i++) {
82 widths[i] = std::max(widths[i], head_and_ruller_line->colnames[i].size());
83 }
84 }
85 }
86 return widths;
87 }
88
89 std::string render() {
90
91 std::vector<size_t> widths = compute_widths();
92
93 std::string print = "";
94 for (auto &line : table_lines) {
95 if (data *data_line = std::get_if<data>(&line)) {
96 print += "\n|";
97 for (u32 i = 0; i < cols_count; i++) {
98 if (data_line->position == left) {
99 print += shambase::format(" {:<{}} |", data_line->cols[i], widths[i]);
100 } else if (data_line->position == right) {
101 print += shambase::format(" {:>{}} |", data_line->cols[i], widths[i]);
102 } else if (data_line->position == center) {
103 print += shambase::format(" {:^{}} |", data_line->cols[i], widths[i]);
104 }
105 }
106
107 } else if (rulled_data *head_and_ruller_line = std::get_if<rulled_data>(&line)) {
108 std::string tmp = "+";
109 for (u32 i = 0; i < cols_count; i++) {
110 tmp += shambase::format(
111 " {:^{}} +", head_and_ruller_line->colnames[i], widths[i]);
112 }
113
114 auto neigh_char_is_good = [&](char c) -> bool {
115 return c == ' ' || c == '-' || c == '<' || c == '>' || c == '+';
116 };
117
118 std::vector<bool> set_to_space = std::vector<bool>(tmp.size(), false);
119 // if the next and previous chars are space and i am a space then set me to true
120 for (size_t i = 1; i < tmp.size() - 1; i++) {
121 if (tmp[i] == ' ' && neigh_char_is_good(tmp[i - 1])
122 && neigh_char_is_good(tmp[i + 1])) {
123 set_to_space[i] = true;
124 }
125 }
126 // replace the spaces by '-'
127 for (size_t i = 0; i < tmp.size() - 1; i++) {
128 if (set_to_space[i]) {
129 tmp[i] = '-';
130 }
131 }
132 print += "\n" + tmp;
133 } else if (rule *rule_line = std::get_if<rule>(&line)) {
134 print += "\n+";
135 for (u32 i = 0; i < cols_count; i++) {
136 print += shambase::format(
137 "-{:<{}}-+", std::string(widths[i], '-'), widths[i]);
138 }
139 } else if (double_rule *double_rule_line = std::get_if<double_rule>(&line)) {
140 print += "\n+";
141 for (u32 i = 0; i < cols_count; i++) {
142 print += shambase::format(
143 "={:<{}}=+", std::string(widths[i], '='), widths[i]);
144 }
145 }
146 }
147 return print;
148 }
149 };
150
151} // namespace shambase
std::uint32_t u32
32 bit unsigned integer
This header file contains utility functions related to exception handling in the code.
namespace for basic c++ utilities
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
void print(std::string_view sv)
Prints a string to the console.
Definition print.cpp:30