Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:37

0001 
0002 // Copyright 2021, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #include "JTablePrinter.h"
0007 #include "JANA/JLogger.h"
0008 
0009 std::vector<std::string> JTablePrinter::SplitContents(std::string contents, size_t max_width) {
0010     auto split_by_newlines = SplitContentsByNewlines(contents);
0011     if (max_width == 0) return split_by_newlines;
0012 
0013     std::vector<std::string> results;
0014     for (auto& s: split_by_newlines) {
0015         auto split_by_spaces = SplitContentsBySpaces(s, max_width);
0016         for (auto& ss : split_by_spaces) {
0017             results.push_back(ss);
0018         }
0019     }
0020     return results;
0021 }
0022 
0023 std::vector<std::string> JTablePrinter::SplitContentsByNewlines(std::string contents) {
0024     std::vector<std::string> split_by_newlines;
0025     size_t contents_width = contents.size();
0026     size_t line_start = 0;
0027     size_t line_end = line_start;
0028     while (line_end < contents_width) {
0029         if (contents[line_end] == '\n') {
0030             split_by_newlines.push_back(contents.substr(line_start, line_end - line_start));
0031             line_start = line_end + 1;
0032             line_end = line_start;
0033         }
0034         line_end += 1;
0035     }
0036     split_by_newlines.push_back(contents.substr(line_start, contents_width - line_start));
0037     return split_by_newlines;
0038 }
0039 
0040 std::vector<std::string> JTablePrinter::SplitContentsBySpaces(std::string contents, size_t max_width) {
0041 
0042     std::vector<std::string> split_by_spaces;
0043     if (contents.size() <= max_width) {
0044         split_by_spaces.push_back(contents);
0045         return split_by_spaces;
0046     }
0047 
0048     size_t split_start = 0;
0049     size_t split_end = 0;
0050     size_t contents_end = contents.size();
0051     for (size_t i = 0; i < contents_end; ++i) {
0052         if (contents[i] == ' ') {
0053             // std::cout << "Found ' ' on i=" << i << std::endl;
0054             split_end = i;
0055             // std::cout << "Setting split = [" << split_start << ", " << split_end << "]" << std::endl;
0056         }
0057         if (i - split_start == max_width) {
0058             // std::cout << "Hit max_width on i=" << i << std::endl;
0059             if (split_end == split_start) {
0060                 split_by_spaces.push_back(contents.substr(split_start, i - split_start));
0061                 // std::cout << "Pushing back " << split_by_spaces.back() << " (no split!)" << std::endl;
0062                 split_start = i;
0063                 split_end = i; // Because we didn't find a split, we don't want to lose any characters here
0064                 // std::cout << "Setting split = [" << split_start << ", " << split_end << "]" << std::endl;
0065             }
0066             else {
0067                 split_by_spaces.push_back(contents.substr(split_start, split_end - split_start));
0068                 // std::cout << "Pushing back " << split_by_spaces.back() << " (found split!)" << std::endl;
0069                 split_start = split_end + 1; // Because we found a split, we want to lose the extra space
0070                 split_end = split_start;
0071                 // std::cout << "Setting split = [" << split_start << ", " << split_end << "]" << std::endl;
0072             }
0073         }
0074     }
0075     split_end = contents_end;
0076     // std::cout << "Setting split = [" << split_start << ", " << split_end << "]" << std::endl;
0077 
0078     split_by_spaces.push_back(contents.substr(split_start, split_end - split_start));
0079     // std::cout << "Pushing back " << split_by_spaces.back() << "(cleanup)" << std::endl;
0080     return split_by_spaces;
0081 }
0082 
0083 JTablePrinter::Column& JTablePrinter::AddColumn(std::string header, Justify justify, int desired_width) {
0084     columns.emplace_back();
0085     Column& col = columns.back();
0086     col.header = std::move(header);
0087     col.contents_width = col.header.size();
0088     col.justify = justify;
0089     col.desired_width = desired_width;
0090     col.use_desired_width = (desired_width != 0);
0091     return col;
0092 }
0093 
0094 
0095 void JTablePrinter::FormatLine(std::ostream& os, std::string contents, int max_width, Justify justify) const {
0096     auto cs = contents.size();
0097 
0098     if (justify == Justify::Left) {
0099         os << std::left << std::setw(max_width) << contents;
0100     }
0101     else if (justify == Justify::Right) {
0102         os << std::right << std::setw(max_width) << contents;
0103     }
0104     else {
0105         int lpad = (max_width-cs)/2; // center slightly to the left
0106         int rpad = (max_width-cs) - lpad;
0107         for (int i=0; i<lpad; ++i) os << " ";
0108         os << contents;
0109         for (int i=0; i<rpad; ++i) os << " ";
0110     }
0111 }
0112 std::string JTablePrinter::Render() const {
0113     std::ostringstream ss;
0114     Render(ss);
0115     return ss.str();
0116 }
0117 
0118 void JTablePrinter::Render(std::ostream& os) const {
0119 
0120     // Calculate table width
0121     int table_width = 0;
0122     for (const Column& col : columns) {
0123         table_width += col.use_desired_width ? col.desired_width : col.contents_width;
0124     }
0125     table_width += (columns.size()-1)*cell_margin;
0126 
0127     // Print top rule
0128     if (top_rule == RuleStyle::Broken) {
0129         for (int i = 0; i<indent; ++i) os << " ";
0130         for (const auto& col : columns) {
0131             int underline_len = (col.use_desired_width)?col.desired_width:col.contents_width;
0132             for (int i=0; i<underline_len; ++i) os << "-";
0133             for (int i=0; i<cell_margin; ++i) os << " ";
0134         }
0135         os << std::endl;
0136     }
0137     else if (top_rule == RuleStyle::Across) {
0138         for (int i = 0; i<indent; ++i) os << " ";
0139         for (int i=0; i<table_width; ++i) os << "-";
0140         os << std::endl;
0141     }
0142 
0143     // Print headings
0144     for (int i = 0; i<indent; ++i) os << " ";
0145     for (const auto& col : columns) {
0146         // os << col.header;
0147         FormatLine(os, col.header, col.use_desired_width ? col.desired_width : col.contents_width, Justify::Center);
0148         for (int i=0; i<cell_margin; ++i) os << " ";
0149     }
0150     os << std::endl;
0151 
0152     // Print header rule
0153     if (header_rule == RuleStyle::Across) {
0154         for (int i = 0; i<indent; ++i) os << " ";
0155         for (int i = 0; i<table_width; ++i) os << "-";
0156         os << std::endl;
0157     }
0158     else if (header_rule == RuleStyle::Broken) {
0159         for (int i = 0; i<indent; ++i) os << " ";
0160         for (const auto& col : columns) {
0161             int underline_len = (col.use_desired_width)?col.desired_width:col.contents_width;
0162             for (int i=0; i<underline_len; ++i) os << "-";
0163             for (int i=0; i<cell_margin; ++i) os << " ";
0164         }
0165         os << std::endl;
0166     }
0167 
0168     // Print rows
0169     for (int row = 0; row < current_row; ++row) {
0170         std::vector<std::vector<std::string>> lines;
0171         size_t line_count = 1;
0172         for (const auto& col : columns) {
0173             auto split = SplitContents(col.values[row], col.desired_width);
0174             lines.push_back(split);
0175             if (split.size() > line_count) line_count = split.size();
0176         }
0177         if (vertical_padding) line_count += 1;
0178 
0179         for (size_t line=0; line < line_count; ++line) {
0180             for (int i = 0; i<indent; ++i) os << " ";
0181 
0182             size_t col_count = columns.size();
0183             for (size_t col = 0; col < col_count; ++col) {
0184                 auto& column = columns[col];
0185                 if (line < lines[col].size()) {
0186                     FormatLine(os, lines[col][line], column.use_desired_width ? column.desired_width : column.contents_width, column.justify);
0187                 }
0188                 else {
0189                     FormatLine(os, "", column.use_desired_width ? column.desired_width : column.contents_width, column.justify);
0190                 }
0191                 for (int i=0; i<cell_margin; ++i) os << " ";
0192             }
0193             os << std::endl;
0194 
0195         }
0196     }
0197 
0198     // Print bottom rule
0199     if (bottom_rule == RuleStyle::Broken) {
0200         for (int i = 0; i<indent; ++i) os << " ";
0201         for (const auto& col : columns) {
0202             int underline_len = (col.use_desired_width)?col.desired_width:col.contents_width;
0203             for (int i=0; i<underline_len; ++i) os << "-";
0204             for (int i=0; i<cell_margin; ++i) os << " ";
0205         }
0206         os << std::endl;
0207     }
0208     else if (bottom_rule == RuleStyle::Across) {
0209         for (int i = 0; i<indent; ++i) os << " ";
0210         for (int i = 0; i<table_width; ++i) os << "-";
0211         os << std::endl;
0212     }
0213 }
0214 
0215 std::ostream& operator<<(std::ostream& os, const JTablePrinter& t) {
0216     t.Render(os);
0217     return os;
0218 }
0219