-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMapping.mpp
More file actions
97 lines (90 loc) · 3.59 KB
/
Mapping.mpp
File metadata and controls
97 lines (90 loc) · 3.59 KB
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
export module CppUtils.Language.CSV.Mapping;
import std;
import CppUtils.String;
import CppUtils.Type.Mapping;
export namespace CppUtils::Language::CSV
{
using Line = std::vector<std::string_view>;
template<class Object, class Mapping>
[[nodiscard]] inline auto toStruct(const auto& csvLine) -> Object
{
using CSVMapping = typename Mapping::CSVMapping;
using StructMapping = typename Mapping::StructMapping;
using FunctionMapping = typename Mapping::FunctionMapping;
static_assert(std::is_default_constructible_v<Object>);
auto object = Object{};
std::apply([&](auto&&... csvPairs) -> void {
([&](auto&& csvPair) -> void {
using CSVPair = std::remove_cvref_t<decltype(csvPair)>;
constexpr auto token = CSVPair::lhs;
constexpr auto csvColumnPosition = std::get<0>(CSVPair::rhs);
if (csvColumnPosition < std::size(csvLine))
{
constexpr auto memberPointer = std::get<0>(StructMapping::template toRhs<token>());
auto& member = object.*memberPointer;
using MemberType = std::remove_cvref_t<decltype(member)>;
auto value = std::string_view{csvLine[csvColumnPosition]};
if constexpr (FunctionMapping::template containsLhs<token>())
FunctionMapping::template toSingleRhs<token>()(member, value);
else if constexpr (std::same_as<MemberType, std::string_view>)
member = value;
else if constexpr (std::same_as<MemberType, std::string>)
member = value;
else if constexpr (std::integral<MemberType> or std::floating_point<MemberType>)
std::from_chars(std::data(value), std::data(value) + std::size(value), member);
}
}(csvPairs), ...);
}, typename CSVMapping::Values{});
return object;
}
template<class Object, class Mapping>
[[nodiscard]] inline auto toStructs(
const auto& lines,
std::size_t dropNFirstLines = 0,
std::vector<Object>&& objects = {}) -> std::vector<Object>
{
for (auto i = dropNFirstLines; i < std::size(lines); ++i)
if (const auto& line = lines[i]; not std::empty(line))
objects.push_back(toStruct<Object, Mapping>(line));
return std::move(objects);
}
template<class Object, class Mapping>
[[nodiscard]] inline auto toCSV(const Object& object, std::string_view separator = ";") -> std::string
{
using CSVMapping = typename Mapping::CSVMapping;
using StructMapping = typename Mapping::StructMapping;
constexpr auto maxPosition = []() -> std::size_t {
auto max = 0uz;
std::apply([&](auto&&... pairs) {
((max = std::max(max, static_cast<std::size_t>(std::get<0>(std::remove_cvref_t<decltype(pairs)>::rhs)))), ...);
}, typename CSVMapping::Values{});
return max;
}();
auto columns = std::vector<std::string>(maxPosition + 1);
std::apply([&](auto&&... csvPairs) -> void {
([&](auto&& csvPair) -> void {
using CSVPair = std::remove_cvref_t<decltype(csvPair)>;
constexpr auto token = CSVPair::lhs;
constexpr auto csvColumnPosition = std::get<0>(CSVPair::rhs);
constexpr auto memberPointer = std::get<0>(StructMapping::template toRhs<token>());
columns[csvColumnPosition] = String::formatValue(object.*memberPointer);
}(csvPairs), ...);
}, typename CSVMapping::Values{});
return columns | std::views::join_with(separator) | std::ranges::to<std::string>();
}
template<class Object, class Mapping>
[[nodiscard]] inline auto toCSV(
const std::vector<Object>& objects,
std::string_view columnSeparator = ";",
std::string_view lineSeparator = "\n") -> std::string
{
auto csv = std::string{};
for (const auto& object : objects)
{
if (not std::empty(csv))
csv += lineSeparator;
csv += toCSV<Object, Mapping>(object, columnSeparator);
}
return csv;
}
}