diff options
author | Dan Mick <dan.mick@inktank.com> | 2012-10-04 23:39:16 +0200 |
---|---|---|
committer | Dan Mick <dan.mick@inktank.com> | 2012-10-05 00:20:29 +0200 |
commit | fb88683cd14d8bc7fc99617512f0980f288194de (patch) | |
tree | 20e0b0587c624b205fabb3db7aae84a6055f8d4f /src/common/TextTable.h | |
parent | librbd: fix error handling in get_parent_info (diff) | |
download | ceph-fb88683cd14d8bc7fc99617512f0980f288194de.tar.xz ceph-fb88683cd14d8bc7fc99617512f0980f288194de.zip |
Add TextTable class for table output
Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'src/common/TextTable.h')
-rw-r--r-- | src/common/TextTable.h | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/common/TextTable.h b/src/common/TextTable.h new file mode 100644 index 00000000000..44d0aa4cd46 --- /dev/null +++ b/src/common/TextTable.h @@ -0,0 +1,159 @@ +// -*- 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. + * + */ +#include <vector> +#include <sstream> +#include <iomanip> +#include <string> +#include "include/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(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 + std::vector<std::vector<std::string> > row; // row data array + unsigned int curcol, currow; // col, row being inserted into + unsigned int indent; // indent width when rendering + +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; } + + /** + * 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 + 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 + oss << std::setw(width) << item; + 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 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, TextTable &t); + + /** + * clear: Reset everything in a TextTable except column defs + * resize cols to heading widths, clear indent + */ + + void clear(); +}; |