summaryrefslogtreecommitdiffstats
path: root/src/common/TextTable.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/common/TextTable.h
parentInitial commit. (diff)
downloadceph-upstream/18.2.2.tar.xz
ceph-upstream/18.2.2.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/common/TextTable.h')
-rw-r--r--src/common/TextTable.h175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/common/TextTable.h b/src/common/TextTable.h
new file mode 100644
index 000000000..6702c0057
--- /dev/null
+++ b/src/common/TextTable.h
@@ -0,0 +1,175 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2012 Inktank Storage, Inc.
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef TEXT_TABLE_H_
+#define TEXT_TABLE_H_
+
+#include <vector>
+#include <sstream>
+#include "include/ceph_assert.h"
+
+/**
+ * TextTable:
+ * Manage tabular output of data. Caller defines heading of each column
+ * and alignment of heading and column data,
+ * then inserts rows of data including tuples of
+ * length (ncolumns) terminated by TextTable::endrow. When all rows
+ * are inserted, caller asks for output with ostream <<
+ * which sizes/pads/dumps the table to ostream.
+ *
+ * Columns autosize to largest heading or datum. One space is printed
+ * between columns.
+ */
+
+class TextTable {
+
+public:
+ enum Align {LEFT = 1, CENTER, RIGHT};
+
+private:
+ struct TextTableColumn {
+ std::string heading;
+ int width;
+ Align hd_align;
+ Align col_align;
+
+ TextTableColumn() {}
+ TextTableColumn(const std::string &h, int w, Align ha, Align ca) :
+ heading(h), width(w), hd_align(ha), col_align(ca) { }
+ ~TextTableColumn() {}
+ };
+
+ std::vector<TextTableColumn> col; // column definitions
+ unsigned int curcol, currow; // col, row being inserted into
+ unsigned int indent; // indent width when rendering
+ std::string column_separation = {" "};
+
+protected:
+ std::vector<std::vector<std::string> > row; // row data array
+
+public:
+ TextTable(): curcol(0), currow(0), indent(0) {}
+ ~TextTable() {}
+
+ /**
+ * Define a column in the table.
+ *
+ * @param heading Column heading string (or "")
+ * @param hd_align Alignment for heading in column
+ * @param col_align Data alignment
+ *
+ * @note alignment is of type TextTable::Align; values are
+ * TextTable::LEFT, TextTable::CENTER, or TextTable::RIGHT
+ *
+ */
+ void define_column(const std::string& heading, Align hd_align,
+ Align col_align);
+
+ /**
+ * Set indent for table. Only affects table output.
+ *
+ * @param i Number of spaces to indent
+ */
+ void set_indent(int i) { indent = i; }
+
+ /**
+ * Set column separation
+ *
+ * @param s String to separate columns
+ */
+ void set_column_separation(const std::string& s) {
+ column_separation = s;
+ }
+
+ /**
+ * Add item to table, perhaps on new row.
+ * table << val1 << val2 << TextTable::endrow;
+ *
+ * @param: value to output.
+ *
+ * @note: Numerics are output in decimal; strings are not truncated.
+ * Output formatting choice is limited to alignment in define_column().
+ *
+ * @return TextTable& for chaining.
+ */
+
+ template<typename T> TextTable& operator<<(const T& item)
+ {
+ if (row.size() < currow + 1)
+ row.resize(currow + 1);
+
+ /**
+ * col.size() is a good guess for how big row[currow] needs to be,
+ * so just expand it out now
+ */
+ if (row[currow].size() < col.size()) {
+ row[currow].resize(col.size());
+ }
+
+ // inserting more items than defined columns is a coding error
+ ceph_assert(curcol + 1 <= col.size());
+
+ // get rendered width of item alone
+ std::ostringstream oss;
+ oss << item;
+ int width = oss.str().length();
+ oss.seekp(0);
+
+ // expand column width if necessary
+ if (width > col[curcol].width) {
+ col[curcol].width = width;
+ }
+
+ // now store the rendered item with its proper width
+ row[currow][curcol] = oss.str();
+
+ curcol++;
+ return *this;
+ }
+
+ /**
+ * Degenerate type/variable here is just to allow selection of the
+ * following operator<< for "<< TextTable::endrow"
+ */
+
+ struct endrow_t {};
+ static constexpr endrow_t endrow{};
+
+ /**
+ * Implements TextTable::endrow
+ */
+
+ TextTable &operator<<(endrow_t)
+ {
+ curcol = 0;
+ currow++;
+ return *this;
+ }
+
+ /**
+ * Render table to ostream (i.e. cout << table)
+ */
+
+ friend std::ostream &operator<<(std::ostream &out, const TextTable &t);
+
+ /**
+ * clear: Reset everything in a TextTable except column defs
+ * resize cols to heading widths, clear indent
+ */
+
+ void clear();
+};
+
+#endif
+