wren
Vulkan-based game engine
Loading...
Searching...
No Matches
format.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <boost/describe.hpp>
4#include <filesystem>
5#include <format>
6#include <vector>
7
9
10template <wren::DescribedStruct T>
11struct std::formatter<T, char> {
12 constexpr auto parse(std::format_parse_context& ctx) {
13 auto it = ctx.begin(), end = ctx.end();
14
15 if (it != end && *it != '}') {
16 throw std::runtime_error("invalid format");
17 }
18
19 return it;
20 }
21
22 auto format(const T& t, format_context& ctx) const {
23 using namespace boost::describe;
24
25 using Bd = describe_bases<T, mod_any_access>;
26 using Md = describe_members<T, mod_any_access>;
27
28 auto out = ctx.out();
29
30 *out++ = '{';
31
32 bool first = true;
33
34 boost::mp11::mp_for_each<Bd>([&](auto d) {
35 if (!first) {
36 *out++ = ',';
37 }
38
39 first = false;
40
41 out = std::format_to(out, " {}", t);
42 });
43
44 boost::mp11::mp_for_each<Md>([&](auto d) {
45 if (!first) {
46 *out++ = ',';
47 }
48
49 first = false;
50
51 out = std::format_to(out, " .{}={}", d.name, t.*d.pointer);
52 });
53
54 if (!first) {
55 *out++ = ' ';
56 }
57
58 *out++ = '}';
59
60 return out;
61 }
62};
63
64template <wren::DescribedEnum T>
65struct std::formatter<T, char> {
66 private:
67 using U = std::underlying_type_t<T>;
68
69 std::formatter<std::string_view, char> sf_;
70 std::formatter<U, char> nf_;
71
72 public:
73 constexpr auto parse(format_parse_context& ctx) {
74 auto i1 = sf_.parse(ctx);
75 auto i2 = nf_.parse(ctx);
76
77 if (i1 != i2) {
78 throw std::runtime_error("invalid format");
79 }
80
81 return i1;
82 }
83
84 auto format(const T& t, format_context& ctx) const {
85 const char* s = boost::describe::enum_to_string(t, 0);
86
87 if (s) {
88 return sf_.format(s, ctx);
89 } else {
90 return nf_.format(static_cast<U>(t), ctx);
91 }
92 }
93};
94
95template <typename T>
96struct std::formatter<std::vector<T>, char> {
97 constexpr auto parse(format_parse_context& ctx) {
98 auto it = ctx.begin(), end = ctx.end();
99
100 if (it != end && *it != '}') {
101 throw std::runtime_error("invalid format");
102 }
103
104 return it;
105 }
106
107 auto format(const std::vector<T>& list, format_context& ctx) const {
108 auto out = ctx.out();
109
110 bool first = true;
111
112 for (const auto& elem : list) {
113 if (!first) *out++ = ',';
114
115 out = std::format_to(out, "{}", elem);
116
117 first = false;
118 }
119
120 return out;
121 }
122};
123
124template <>
125struct std::formatter<std::filesystem::path, char> {
126 constexpr auto parse(format_parse_context& ctx) {
127 auto it = ctx.begin(), end = ctx.end();
128
129 if (it != end && *it != '}') {
130 throw std::runtime_error("invalid format");
131 }
132
133 return it;
134 }
135
136 auto format(const std::filesystem::path& path, format_context& ctx) const {
137 return std::format_to(ctx.out(), "{}", path.string());
138 }
139};
std::formatter< std::string_view, char > sf_
Definition format.hpp:69
std::formatter< U, char > nf_
Definition format.hpp:70
auto format(const T &t, format_context &ctx) const
Definition format.hpp:22
constexpr auto parse(std::format_parse_context &ctx)
Definition format.hpp:12
std::underlying_type_t< T > U
Definition format.hpp:67
constexpr auto parse(format_parse_context &ctx)
Definition format.hpp:73
constexpr auto parse(format_parse_context &ctx)
Definition format.hpp:126
auto format(const std::filesystem::path &path, format_context &ctx) const
Definition format.hpp:136
auto format(const std::vector< T > &list, format_context &ctx) const
Definition format.hpp:107
constexpr auto parse(format_parse_context &ctx)
Definition format.hpp:97