This repository has been archived by the owner on May 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
rowset.hpp
117 lines (100 loc) · 3.24 KB
/
rowset.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Andrew Naplavkov
#ifndef BARK_DB_ROWSET_HPP
#define BARK_DB_ROWSET_HPP
#include <bark/db/variant.hpp>
#include <bark/detail/unicode.hpp>
#include <cctype>
#include <string>
namespace bark::db {
/// An arrangement of @ref variant_t in rows and columns
struct rowset {
std::vector<std::string> columns;
blob data;
};
/// Returns tuples of @ref variant_t
inline auto select(const rowset& from)
{
auto res = std::vector<std::vector<variant_t>>{};
for (auto is = variant_istream{from.data}; !is.data.empty();)
for (auto& var : res.emplace_back(from.columns.size()))
is >> var;
return res;
}
/// Returns tuples of @ref variant_t
template <class Columns>
auto select(const Columns& cols, const rowset& from)
{
auto idxs = as<std::vector<size_t>>(from.columns, [&](auto&& col) {
auto it = std::find(std::begin(cols), std::end(cols), col);
return std::distance(std::begin(cols), it);
});
auto res = std::vector<std::vector<variant_t>>{};
for (auto is = variant_istream{from.data}; !is.data.empty();) {
auto& row = res.emplace_back(idxs.size());
for (size_t idx : idxs)
if (idx < row.size())
is >> row[idx];
else
read(is);
}
return res;
}
namespace detail {
inline std::string format(const variant_t& src, const std::ostream& dest)
{
std::ostringstream os;
os.copyfmt(dest);
os << src;
auto res = os.str();
std::replace_if(
res.begin(), res.end(), [](char ch) { return std::isspace(ch); }, ' ');
return res;
}
struct line {
std::vector<size_t>& sizes;
const std::vector<variant_t>& row;
void fit(const std::ostream& dest)
{
for (size_t i = 0; i < sizes.size(); ++i)
sizes[i] = std::max(sizes[i], unicode::size(format(row[i], dest)));
}
friend std::ostream& operator<<(std::ostream& dest, const line& src)
{
for (size_t i = 0; i < src.sizes.size(); ++i) {
auto str = format(src.row[i], dest);
auto indent = src.sizes[i] - unicode::size(str);
dest << "|" << std::setw(1) << "";
if (std::holds_alternative<std::string_view>(src.row[i]))
dest << str << std::setw(indent) << "";
else
dest << std::setw(indent) << "" << str;
dest << std::setw(1) << "";
}
return dest << "|\n";
}
};
} // namespace detail
inline std::ostream& operator<<(std::ostream& dest, const rowset& src)
{
using row_t = std::vector<variant_t>;
auto columns = as<row_t>(src.columns);
auto rows = select(src);
auto sizes = std::vector<size_t>(columns.size());
detail::line{sizes, columns}.fit(dest);
for (auto& row : rows)
detail::line{sizes, row}.fit(dest);
dest << std::setfill(' ') << detail::line{sizes, columns}
<< std::setfill('-') << detail::line{sizes, row_t(columns.size())}
<< std::setfill(' ');
for (auto& row : rows)
dest << detail::line{sizes, row};
return dest;
}
template <class Rows, class Functor>
void for_each_blob(const Rows& rows, size_t col, Functor f)
{
for (auto& row : rows)
f(std::get<bark::blob_view>(row[col]));
}
} // namespace bark::db
#endif // BARK_DB_ROWSET_HPP