]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/TextTable.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / TextTable.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2012 Inktank Storage, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #ifndef TEXT_TABLE_H_
16 #define TEXT_TABLE_H_
17
18 #include <vector>
19 #include <sstream>
20 #include <iomanip>
21 #include <string>
22 #include "include/assert.h"
23
24 /**
25 * TextTable:
26 * Manage tabular output of data. Caller defines heading of each column
27 * and alignment of heading and column data,
28 * then inserts rows of data including tuples of
29 * length (ncolumns) terminated by TextTable::endrow. When all rows
30 * are inserted, caller asks for output with ostream <<
31 * which sizes/pads/dumps the table to ostream.
32 *
33 * Columns autosize to largest heading or datum. One space is printed
34 * between columns.
35 */
36
37 class TextTable {
38
39 public:
40 enum Align {LEFT = 1, CENTER, RIGHT};
41
42 private:
43 struct TextTableColumn {
44 std::string heading;
45 int width;
46 Align hd_align;
47 Align col_align;
48
49 TextTableColumn() {}
50 TextTableColumn(std::string h, int w, Align ha, Align ca) :
51 heading(h), width(w), hd_align(ha), col_align(ca) { }
52 ~TextTableColumn() {}
53 };
54
55 std::vector<TextTableColumn> col; // column definitions
56 unsigned int curcol, currow; // col, row being inserted into
57 unsigned int indent; // indent width when rendering
58
59 protected:
60 std::vector<std::vector<std::string> > row; // row data array
61
62 public:
63 TextTable(): curcol(0), currow(0), indent(0) {}
64 ~TextTable() {}
65
66 /**
67 * Define a column in the table.
68 *
69 * @param heading Column heading string (or "")
70 * @param hd_align Alignment for heading in column
71 * @param col_align Data alignment
72 *
73 * @note alignment is of type TextTable::Align; values are
74 * TextTable::LEFT, TextTable::CENTER, or TextTable::RIGHT
75 *
76 */
77 void define_column(const std::string& heading, Align hd_align,
78 Align col_align);
79
80 /**
81 * Set indent for table. Only affects table output.
82 *
83 * @param i Number of spaces to indent
84 */
85 void set_indent(int i) { indent = i; }
86
87 /**
88 * Add item to table, perhaps on new row.
89 * table << val1 << val2 << TextTable::endrow;
90 *
91 * @param: value to output.
92 *
93 * @note: Numerics are output in decimal; strings are not truncated.
94 * Output formatting choice is limited to alignment in define_column().
95 *
96 * @return TextTable& for chaining.
97 */
98
99 template<typename T> TextTable& operator<<(const T& item)
100 {
101 if (row.size() < currow + 1)
102 row.resize(currow + 1);
103
104 /**
105 * col.size() is a good guess for how big row[currow] needs to be,
106 * so just expand it out now
107 */
108 if (row[currow].size() < col.size()) {
109 row[currow].resize(col.size());
110 }
111
112 // inserting more items than defined columns is a coding error
113 assert(curcol + 1 <= col.size());
114
115 // get rendered width of item alone
116 std::ostringstream oss;
117 oss << item;
118 int width = oss.str().length();
119 oss.seekp(0);
120
121 // expand column width if necessary
122 if (width > col[curcol].width) {
123 col[curcol].width = width;
124 }
125
126 // now store the rendered item with its proper width
127 row[currow][curcol] = oss.str();
128
129 curcol++;
130 return *this;
131 }
132
133 /**
134 * Degenerate type/variable here is just to allow selection of the
135 * following operator<< for "<< TextTable::endrow"
136 */
137
138 struct endrow_t {};
139 static endrow_t endrow;
140
141 /**
142 * Implements TextTable::endrow
143 */
144
145 TextTable &operator<<(endrow_t)
146 {
147 curcol = 0;
148 currow++;
149 return *this;
150 }
151
152 /**
153 * Render table to ostream (i.e. cout << table)
154 */
155
156 friend std::ostream &operator<<(std::ostream &out, const TextTable &t);
157
158 /**
159 * clear: Reset everything in a TextTable except column defs
160 * resize cols to heading widths, clear indent
161 */
162
163 void clear();
164 };
165
166 #endif
167