ConsoleTable.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include "ConsoleTable.h"
  19. #include <algorithm>
  20. #include <iostream>
  21. using namespace std;
  22. namespace KC {
  23. /**
  24. * Creates a static string table in set sizes
  25. *
  26. * @param[in] rows number of rows in the table (if exceeding, table will be printed and cleared)
  27. * @param[in] columns exact number of columns
  28. */
  29. ConsoleTable::ConsoleTable(size_t rows, size_t columns) : m_iRows(rows), m_iColumns(columns)
  30. {
  31. m_nRow = 0;
  32. m_vTable.resize(rows);
  33. for (size_t i = 0; i < rows; ++i)
  34. m_vTable[i].resize(columns);
  35. m_vMaxLengths.resize(m_iColumns);
  36. m_vHeader.resize(m_iColumns);
  37. bHaveHeader = false;
  38. }
  39. /**
  40. * Removes all contents from the current table
  41. */
  42. void ConsoleTable::Clear()
  43. {
  44. // remove all data by using resize to 0 and back to original size
  45. m_vTable.resize(0);
  46. m_vTable.resize(m_iRows);
  47. for (size_t i = 0; i < m_iRows; ++i)
  48. m_vTable[i].resize(m_iColumns);
  49. m_vMaxLengths.clear();
  50. m_vHeader.clear();
  51. m_nRow = 0;
  52. bHaveHeader = false;
  53. }
  54. /**
  55. * Removes all contents from the current table and makes the table size in the new given size
  56. *
  57. * @param[in] rows guessed number of rows in the table
  58. * @param[in] columns exact number of columns
  59. */
  60. void ConsoleTable::Resize(size_t rows, size_t columns)
  61. {
  62. m_nRow = 0;
  63. bHaveHeader = false;
  64. m_iRows = rows;
  65. m_iColumns = columns;
  66. m_vTable.resize(rows);
  67. for (size_t i = 0; i < rows; ++i)
  68. m_vTable[i].resize(columns);
  69. m_vMaxLengths.resize(m_iColumns);
  70. m_vHeader.resize(m_iColumns);
  71. }
  72. /**
  73. * Sets the header name for a column. This is optional, as not all tables have headers.
  74. *
  75. * @param[in] col column numer to set header name for
  76. * @param[in] entry name of the header
  77. * @retval true on success, false if offsets are out of range
  78. */
  79. bool ConsoleTable::SetHeader(size_t col, const string& entry)
  80. {
  81. size_t len;
  82. if (col >= m_iColumns)
  83. return false;
  84. m_vHeader[col] = m_converter.convert_to<wstring>(CHARSET_WCHAR, entry, entry.length(), CHARSET_CHAR);
  85. len = entry.length();
  86. if (len > m_vMaxLengths[col])
  87. m_vMaxLengths[col] = len;
  88. bHaveHeader = true;
  89. return true;
  90. }
  91. /**
  92. * Adds entry at column in the table at the given column. Row
  93. * increments automatically after setting last column of table.
  94. *
  95. * @param[in] col column offset of the table, starting at 0
  96. * @param[in] entry utf-8 string to set in the table in current terminal charset
  97. * @retval true on success, false if offsets are out of range
  98. */
  99. bool ConsoleTable::AddColumn(size_t col, const string& entry)
  100. {
  101. if (col >= m_iColumns)
  102. return false;
  103. if (m_nRow >= m_iRows) {
  104. PrintTable();
  105. Clear();
  106. }
  107. SetColumn(m_nRow, col, entry);
  108. return true;
  109. }
  110. /**
  111. * Sets entry in the table at the given offsets
  112. *
  113. * @param[in] row row offset of the table, starting at 0
  114. * @param[in] col column offset of the table, starting at 0
  115. * @param[in] entry utf-8 string to set in the table in current terminal charset
  116. * @retval true on success, false if offsets are out of range
  117. */
  118. bool ConsoleTable::SetColumn(size_t row, size_t col, const string& entry)
  119. {
  120. size_t len;
  121. if (col >= m_iColumns || row >= m_iRows)
  122. return false;
  123. // we want to count number of printable characters, which is not possible using UTF-8
  124. m_vTable[row][col] = m_converter.convert_to<wstring>(CHARSET_WCHAR, entry, entry.length(), CHARSET_CHAR);
  125. len = m_vTable[row][col].length();
  126. if (len > m_vMaxLengths[col])
  127. m_vMaxLengths[col] = len;
  128. m_nRow = row;
  129. if (col+1 == m_iColumns)
  130. ++m_nRow;
  131. return true;
  132. }
  133. /**
  134. * Prints one row of a table
  135. *
  136. * @param[in] vRow reference to the row wanted on the screen
  137. */
  138. void ConsoleTable::PrintRow(const vector<wstring>& vRow)
  139. {
  140. size_t nCol = 0;
  141. size_t longest, ntabs;
  142. cout << '\t';
  143. for (const auto &col : vRow) {
  144. // cout can't print wstring, and wcout is not allowed to mix with cout.
  145. printf("%ls\t", col.c_str());
  146. if (nCol+1 < m_iColumns) {
  147. longest = ((m_vMaxLengths[nCol] /8) +1);
  148. ntabs = longest - ((col.length() / 8) + 1);
  149. cout << string(ntabs, '\t');
  150. }
  151. ++nCol;
  152. }
  153. cout << endl;
  154. }
  155. /**
  156. * Dumps one row of a table as comma separated fields
  157. *
  158. * @param[in] vRow reference to the row wanted on the screen
  159. */
  160. void ConsoleTable::DumpRow(const vector<wstring>& vRow)
  161. {
  162. size_t nCol = 0;
  163. for (const auto &col : vRow) {
  164. std::wstring temp = col;
  165. std::replace(temp.begin(), temp.end(), '\n', ' ');
  166. // cout can't print wstring, and wcout is not allowed to mix with cout.
  167. printf("%ls", temp.c_str());
  168. if (nCol + 1 < m_iColumns)
  169. printf(";");
  170. ++nCol;
  171. }
  172. printf("\n");
  173. }
  174. /**
  175. * Prints the table on screen
  176. */
  177. void ConsoleTable::PrintTable()
  178. {
  179. if (bHaveHeader) {
  180. PrintRow(m_vHeader);
  181. size_t total = 0;
  182. for (size_t nCol = 0; nCol < m_iColumns; ++nCol)
  183. total += m_vMaxLengths[nCol];
  184. total += (m_iColumns -1) * 8;
  185. cout << "\t" << string(total, '-') << endl;
  186. }
  187. for (size_t nRow = 0; nRow < m_nRow; ++nRow)
  188. PrintRow(m_vTable[nRow]);
  189. }
  190. /**
  191. * Dumps the table as comma separated fields
  192. */
  193. void ConsoleTable::DumpTable()
  194. {
  195. if (bHaveHeader) {
  196. DumpRow(m_vHeader);
  197. }
  198. for (size_t nRow = 0; nRow < m_nRow; ++nRow)
  199. DumpRow(m_vTable[nRow]);
  200. }
  201. } /* namespace */