Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 "include/assert.h"
21
22 /**
23  * TextTable:
24  * Manage tabular output of data.  Caller defines heading of each column
25  * and alignment of heading and column data,
26  * then inserts rows of data including tuples of
27  * length (ncolumns) terminated by TextTable::endrow.  When all rows
28  * are inserted, caller asks for output with ostream <<
29  * which sizes/pads/dumps the table to ostream.
30  *
31  * Columns autosize to largest heading or datum.  One space is printed
32  * between columns.
33  */
34
35 class TextTable {
36
37 public:
38   enum Align {LEFT = 1, CENTER, RIGHT};
39
40 private:
41   struct TextTableColumn {
42     std::string heading;
43     int width;
44     Align hd_align;
45     Align col_align;
46
47     TextTableColumn() {}
48     TextTableColumn(std::string h, int w, Align ha, Align ca) :
49                     heading(h), width(w), hd_align(ha), col_align(ca) { }
50     ~TextTableColumn() {}
51   };
52
53   std::vector<TextTableColumn> col;     // column definitions
54   unsigned int curcol, currow;          // col, row being inserted into
55   unsigned int indent;                  // indent width when rendering
56
57 protected:
58   std::vector<std::vector<std::string> > row;   // row data array
59
60 public:
61   TextTable(): curcol(0), currow(0), indent(0) {}
62   ~TextTable() {}
63
64   /**
65    * Define a column in the table.
66    *
67    * @param heading Column heading string (or "")
68    * @param hd_align Alignment for heading in column
69    * @param col_align Data alignment
70    *
71    * @note alignment is of type TextTable::Align; values are
72    * TextTable::LEFT, TextTable::CENTER, or TextTable::RIGHT
73    *
74    */
75   void define_column(const std::string& heading, Align hd_align,
76                      Align col_align);
77
78   /**
79    * Set indent for table.  Only affects table output.
80    *
81    * @param i Number of spaces to indent
82    */
83   void set_indent(int i) { indent = i; }
84
85   /**
86    * Add item to table, perhaps on new row.
87    * table << val1 << val2 << TextTable::endrow;
88    *
89    * @param: value to output.
90    *
91    * @note: Numerics are output in decimal; strings are not truncated.
92    * Output formatting choice is limited to alignment in define_column().
93    *
94    * @return TextTable& for chaining.
95    */
96
97   template<typename T> TextTable& operator<<(const T& item)
98   {
99     if (row.size() < currow + 1)
100       row.resize(currow + 1);
101
102     /**
103      * col.size() is a good guess for how big row[currow] needs to be,
104      * so just expand it out now
105      */
106     if (row[currow].size() < col.size()) {
107       row[currow].resize(col.size());
108     }
109
110     // inserting more items than defined columns is a coding error
111     assert(curcol + 1 <= col.size());
112
113     // get rendered width of item alone
114     std::ostringstream oss;
115     oss << item;
116     int width = oss.str().length();
117     oss.seekp(0);
118
119     // expand column width if necessary
120     if (width > col[curcol].width) {
121       col[curcol].width = width;
122     }
123
124     // now store the rendered item with its proper width
125     row[currow][curcol] = oss.str();
126
127     curcol++;
128     return *this;
129   }
130
131   /**
132    * Degenerate type/variable here is just to allow selection of the
133    * following operator<< for "<< TextTable::endrow"
134    */
135
136   struct endrow_t {};
137   static endrow_t endrow;
138
139   /**
140    * Implements TextTable::endrow
141    */
142
143   TextTable &operator<<(endrow_t)
144   {
145     curcol = 0;
146     currow++;
147     return *this;
148   }
149
150   /**
151    * Render table to ostream (i.e. cout << table)
152    */
153
154   friend std::ostream &operator<<(std::ostream &out, const TextTable &t);
155
156   /**
157    * clear: Reset everything in a TextTable except column defs
158    * resize cols to heading widths, clear indent
159    */
160
161   void clear();
162 };
163
164 #endif
165