Ultra 0.9.4
Loading...
Searching...
No Matches
value_format.h
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_VALUE_FORMAT_H)
14#define ULTRA_VALUE_FORMAT_H
15
16#include "kernel/value.h"
17#include "kernel/nullary.h"
19
20#include <format>
21#include <string_view>
22#include <type_traits>
23#include <utility>
24
25namespace ultra::detail
26{
27
28// Minimal `std::quoted`-like escaping for " and \.
29template<class Out>
30Out format_quoted(Out out, std::string_view s)
31{
32 *out++ = '"';
33
34 for (auto ch : s)
35 if (ch == '"' || ch == '\\')
36 {
37 *out++ = '\\';
38 *out++ = ch;
39 }
40 else
41 *out++ = ch;
42
43 *out++ = '"';
44 return out;
45}
46
47} // namespace ultra::detail
48
49
50template<>
51struct std::formatter<ultra::value_t, char>
52{
53 constexpr auto parse(std::format_parse_context &ctx)
54 {
55 // Only allow "{}" (no custom specifiers).
56 auto it(ctx.begin());
57 if (it != ctx.end() && *it != '}')
58 throw std::format_error("Invalid format specifier for ultra::value_t");
59 return it;
60 }
61
62 template<class FormatContext>
63 auto format(const ultra::value_t &v, FormatContext &ctx) const
64 {
65 return std::visit(
66 [&ctx](const auto &x) -> typename FormatContext::iterator
67 {
68 using T = std::remove_cvref_t<decltype(x)>;
69
70 if constexpr (std::is_same_v<T, ultra::D_VOID>)
71 return std::format_to(ctx.out(), "{{}}");
72
73 else if constexpr (std::is_same_v<T, ultra::D_INT>
74 || std::is_same_v<T, ultra::D_DOUBLE>)
75 return std::format_to(ctx.out(), "{}", x);
76
77 else if constexpr (std::is_same_v<T, ultra::D_STRING>)
78 return ultra::detail::format_quoted(ctx.out(), x);
79
80 else if constexpr (std::is_same_v<T, const ultra::D_NULLARY *>)
81 return x ? std::format_to(ctx.out(), "{}", x->to_string())
82 : std::format_to(ctx.out(), "<nullary:null>");
83
84 else if constexpr (std::is_same_v<T, ultra::D_ADDRESS>)
85 return std::format_to(ctx.out(), "[{}]", std::to_underlying(x));
86
87 else if constexpr (std::is_same_v<T, const ultra::D_VARIABLE *>)
88 return x ? std::format_to(ctx.out(), "{}", x->to_string())
89 : std::format_to(ctx.out(), "<var:null>");
90
91 else if constexpr (std::is_same_v<T, ultra::D_IVECTOR>)
92 {
93 auto out(ctx.out());
94 *out++ = '{';
95
96 if (!x.empty())
97 {
98 out = std::format_to(out, "{}", x[0]);
99
100 for (std::size_t i(1); i < x.size(); ++i)
101 out = std::format_to(out, " {}", x[i]);
102 }
103
104 *out++ = '}';
105 return out;
106 }
107
108 else
109 static_assert(!sizeof(T), "Unhandled alternative in ultra::value_t");
110 },
111 v);
112 }
113};
114
115#endif // include guard
std::variant< D_VOID, D_INT, D_DOUBLE, D_STRING, const D_NULLARY *, D_ADDRESS, const D_VARIABLE *, D_IVECTOR > value_t
Definition value.h:54