1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef INPUT_TABLE_DUMP_H
17 #define INPUT_TABLE_DUMP_H
18
19 #include <iomanip>
20 #include <iostream>
21 #include <sstream>
22 #include <string>
23 #include <tuple>
24 #include <vector>
25
26 namespace OHOS {
27 namespace MMI {
28 constexpr size_t EXTRA_CHARACTERS_COUNT { 3 };
29 constexpr int32_t ELEMENT_SPACE_COUNT { 2 };
30
31 template<typename T>
getElementLength(const T & element)32 inline size_t getElementLength(const T &element)
33 {
34 std::ostringstream oss;
35 oss << element;
36 return oss.str().size();
37 }
38
39 template<typename... Titles, typename... Args>
CalculateColumnWidths(const std::tuple<Titles...> & titles,const std::vector<std::tuple<Args...>> & rows,size_t & lineWidth)40 inline std::vector<size_t> CalculateColumnWidths(const std::tuple<Titles...> &titles,
41 const std::vector<std::tuple<Args...>> &rows,
42 size_t &lineWidth)
43 {
44 std::vector<size_t> widths(sizeof...(Titles), 0);
45 auto updateWidths = [&widths](const auto &... field) {
46 size_t index = 0;
47 ((widths[index] = std::max(widths[index], getElementLength(field)), ++index), ...);
48 };
49 std::apply(updateWidths, titles);
50 for (const auto &row: rows) {
51 std::apply(updateWidths, row);
52 }
53 std::for_each(widths.begin(), widths.end(),
54 [&lineWidth](size_t width) { lineWidth += width + EXTRA_CHARACTERS_COUNT; });
55 lineWidth += 1;
56 return widths;
57 }
58
PrintLine(std::ostream & os,const std::vector<size_t> & widths)59 inline void PrintLine(std::ostream &os, const std::vector<size_t> &widths)
60 {
61 os << "+";
62 for (const size_t &width: widths) {
63 os << std::setw(static_cast<int32_t>(width) + ELEMENT_SPACE_COUNT) << std::left << std::setfill('-')
64 << "" << "+";
65 }
66 os << std::setfill(' ') << std::endl;
67 }
68
69 template<typename T>
PrintCentered(std::ostream & os,const T & value,size_t width)70 inline void PrintCentered(std::ostream &os, const T &value, size_t width)
71 {
72 std::ostringstream oss;
73 oss << value;
74 std::string str = oss.str();
75 size_t padding_left = (width - str.size()) / 2;
76 size_t padding_right = width - str.size() - padding_left;
77 os << std::string(padding_left, ' ') << str << std::string(padding_right, ' ');
78 }
79
80 template<typename... Titles>
PrintHeader(std::ostream & os,const std::vector<size_t> & widths,Titles...titles)81 inline void PrintHeader(std::ostream &os, const std::vector<size_t> &widths, Titles... titles)
82 {
83 os << "|";
84 size_t index = 0;
85 ((os << " ", PrintCentered(os, titles, widths[index++]), os << " |"), ...);
86 os << std::endl;
87 }
88
89 template<typename... Args>
PrintRow(std::ostream & os,const std::vector<size_t> & widths,Args...args)90 inline void PrintRow(std::ostream &os, const std::vector<size_t> &widths, Args... args)
91 {
92 os << "|";
93 size_t index = 0;
94 ((os << " ", PrintCentered(os, args, widths[index++]), os << " |"), ...);
95 os << std::endl;
96 }
97
98 template<typename... Titles, typename... Args>
DumpFullTable(std::ostream & os,const std::string & tableName,const std::tuple<Titles...> & titles,const std::vector<std::tuple<Args...>> & rows)99 inline void DumpFullTable(std::ostream &os, const std::string &tableName, const std::tuple<Titles...> &titles,
100 const std::vector<std::tuple<Args...>> &rows)
101 {
102 static_assert(sizeof...(Titles) == sizeof...(Args), "Number of titles must match number of columns in each row");
103
104 // 计算每一列的最大宽度
105 size_t lineWidth = 0;
106 std::vector<size_t> widths = CalculateColumnWidths(titles, rows, lineWidth);
107
108 // 打印表名称
109 PrintCentered(os, tableName, lineWidth);
110 os << std::endl;
111
112 // 打印标题行
113 PrintLine(os, widths);
114 std::apply([&os, &widths](auto &&... args) { PrintHeader(os, widths, args...); }, titles);
115 PrintLine(os, widths);
116
117 // 打印每一行数据
118 for (const auto &row: rows) {
119 std::apply([&os, &widths](auto &&... args) { PrintRow(os, widths, args...); }, row);
120 PrintLine(os, widths);
121 }
122 }
123 } // namespace MMI
124 } // namespace OHOS
125 #endif //INPUT_TABLE_DUMP_H
126