Line data Source code
1 : /** \file textTable.hpp
2 : * \brief declares and defines a simple text table manager
3 : *
4 : * \author Jared R. Males (jaredmales@gmail.com)
5 : *
6 : * \ingroup asciiutils
7 : *
8 : */
9 :
10 : //***********************************************************************//
11 : // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
12 : //
13 : // This file is part of mxlib.
14 : //
15 : // mxlib is free software: you can redistribute it and/or modify
16 : // it under the terms of the GNU General Public License as published by
17 : // the Free Software Foundation, either version 3 of the License, or
18 : // (at your option) any later version.
19 : //
20 : // mxlib is distributed in the hope that it will be useful,
21 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 : // GNU General Public License for more details.
24 : //
25 : // You should have received a copy of the GNU General Public License
26 : // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27 : //***********************************************************************//
28 :
29 : #ifndef textTable_hpp
30 : #define textTable_hpp
31 :
32 : #include <string>
33 : #include <sstream>
34 :
35 : #include "../mxlib.hpp"
36 :
37 : #include "stringUtils.hpp"
38 :
39 : /// The mxlib c++ namespace
40 : namespace mx
41 : {
42 : namespace ioutils
43 : {
44 :
45 : /** \addtogroup asciiutils
46 : * @{
47 : */
48 :
49 : /// An ascii table formatter
50 : /** Manages a table of string content, including word-wrapping within cells.
51 : * Contents are output to an ostream line by line with a table structure.
52 : *
53 : * \todo have ability to add whole row, with a variadic template to handle different types
54 : * \todo allow non-wrapping (i.e. unlimited width) columns
55 : * \todo headers and footers
56 : * \todo add centering (h and v) and right and bottom justification
57 : * \todo have a latex() setup function
58 : * \todo add sort capability, with vector of column choices to sort first by column N, then M, etc.
59 : */
60 : struct textTable
61 : {
62 : std::vector<int> m_colWidths; ///< The widths of each column, not including the separator.
63 :
64 : /// The table cells.
65 : /** Organized as rows.cells.lines, where a cell could be multiple lines.
66 : */
67 : std::vector<std::vector<std::vector<std::string>>> m_rows;
68 :
69 : std::string m_lineStart; ///< Text to print at the beginning of the line.
70 :
71 : std::string m_lineEnd; ///< Text to print at the end of the line.
72 :
73 : std::string m_colSep; ///< Text to print between each column.
74 :
75 : std::string m_rowSep; ///< Text to print between each row.
76 :
77 : /// Add one cell to the table, overwriting if it already exists.
78 : void addCell( size_t row, ///< [in] the row of the cell.
79 : size_t col, ///< [in] the column of the cell.
80 : const std::string &cell ///< [in] the new contents of the cell, will be wrapped.
81 : );
82 :
83 : void addCell( size_t row, ///< [in] the row of the cell.
84 : size_t col, ///< [in] the column of the cell.
85 : const char *cell ///< [in] the new contents of the cell, will be wrapped.
86 : );
87 :
88 : /// Add one cell to the table, overwriting if it already exists.
89 : template <typename typeT>
90 : void addCell( size_t row, ///< [in] the row of the cell.
91 : size_t col, ///< [in] the column of the cell.
92 : const typeT &cell, ///< [in] the new contents of the cell, will be wrapped.
93 : int precision = 0 );
94 :
95 : /// Output the table to a stream
96 : /** Prints the table to the stream, with separators, etc.
97 : *
98 : * \tparam iosT is a std::ostream-like type.
99 : */
100 : template <typename iosT>
101 : void outPut( iosT &ios /**< [in] a std::ostream-like stream.*/ );
102 : };
103 :
104 : template <typename typeT>
105 : void textTable::addCell( size_t row, size_t col, const typeT &cell, int precision )
106 : {
107 : addCell( row, col, convertToString<typeT>( cell, precision ) );
108 : }
109 :
110 : template <typename iosT>
111 2 : void textTable::outPut( iosT &ios )
112 : {
113 2 : std::string line;
114 :
115 2 : size_t width = 0;
116 12 : for( size_t i = 0; i < m_colWidths.size(); ++i )
117 10 : width += m_colWidths[i];
118 2 : width += m_colWidths.size() * ( m_colSep.length() - 1 ); //+100;
119 :
120 2 : line.resize( width, ' ' );
121 :
122 5 : for( size_t i = 0; i < m_rows.size(); ++i )
123 : {
124 3 : size_t rowL = 0;
125 18 : for( size_t j = 0; j < m_colWidths.size(); ++j )
126 : {
127 15 : if( m_rows[i][j].size() > rowL )
128 3 : rowL = m_rows[i][j].size();
129 : }
130 :
131 6 : for( size_t k = 0; k < rowL; ++k )
132 : {
133 : // line.insert( 0, line.length(), ' ');
134 3 : line.clear();
135 3 : line.resize( width, ' ' );
136 : // line.replace(0, width, width, ' ');
137 :
138 3 : size_t startPos = 0;
139 18 : for( size_t j = 0; j < m_colWidths.size(); ++j )
140 : {
141 15 : if( m_rows[i][j].size() > k )
142 13 : line.replace( startPos, m_rows[i][j][k].length(), m_rows[i][j][k] );
143 15 : startPos += m_colWidths[j];
144 :
145 15 : if( j < m_colWidths.size() - 1 )
146 12 : line.replace( startPos, m_colSep.length(), m_colSep );
147 15 : startPos += m_colSep.length();
148 : }
149 :
150 3 : ios << m_lineStart << line << m_lineEnd << "\n";
151 : }
152 :
153 3 : if( m_rowSep.length() > 0 )
154 0 : ios << m_rowSep << "\n";
155 : }
156 2 : }
157 :
158 : extern template void textTable::outPut<std::ostream>( std::ostream &ios );
159 :
160 : /// @}
161 :
162 : } // namespace ioutils
163 : } // namespace mx
164 :
165 : #endif // textTable_hpp
|