Ultra 0.9.4
Loading...
Searching...
No Matches
individual_format.h
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_INDIVIDUAL_FORMAT_H)
14#define ULTRA_INDIVIDUAL_FORMAT_H
15
16#include "kernel/individual.h"
17
18#include <algorithm>
19#include <concepts>
20#include <format>
21#include <iosfwd>
22
23namespace ultra
24{
25
26std::ostream &operator<<(std::ostream &, const individual &);
27
28namespace out
29{
30
31print_format_t print_format_flag(std::ostream &);
32
33class print_format
34{
35public:
36 explicit print_format(print_format_t t) : t_(t) {}
37
38 friend std::ostream &operator<<(std::ostream &, print_format);
39
40private:
42};
43
44std::ostream &c_language(std::ostream &);
45std::ostream &cpp_language(std::ostream &);
46std::ostream &dump(std::ostream &);
47std::ostream &graphviz(std::ostream &);
48std::ostream &in_line(std::ostream &);
49std::ostream &list(std::ostream &);
50std::ostream &python_language(std::ostream &);
51std::ostream &tree(std::ostream &);
52
53} // namespace out
54} // namespace ultra
55
56namespace std
57{
58
59template<> struct formatter<ultra::individual, char>
60{
61 ultra::out::print_format_t fmt_ = ultra::out::list_f;
62
63 [[nodiscard]] constexpr auto parse(std::format_parse_context &ctx)
64 {
65 auto it(ctx.begin());
66 const auto end(ctx.end());
67
68 if (it == end || *it == '}')
69 return it;
70
71 const auto consume([&]<std::size_t N>(const char (&s)[N],
73 {
74 auto probe(it);
75
76 for (std::size_t i(0); i < N - 1; ++i)
77 {
78 if (probe == end || *probe != s[i])
79 return false;
80 ++probe;
81 }
82
83 fmt_ = f;
84 it = probe;
85 return true;
86 });
87
88 // Test longer prefixes first (remember "cpp" starts with "c", so `{:cpp}`
89 // will match "c" first, then fail on trailing characters "pp").
90 if (consume("graphviz", ultra::out::graphviz_f)
91 || consume("python", ultra::out::python_language_f)
92 || consume("inline", ultra::out::in_line_f)
93 || consume("dump", ultra::out::dump_f)
94 || consume("list", ultra::out::list_f)
95 || consume("tree", ultra::out::tree_f)
96 || consume("cpp", ultra::out::cpp_language_f)
97 || consume("c", ultra::out::c_language_f))
98 {
99 if (it != end && *it != '}')
100 throw std::format_error("invalid trailing format specifier for "
101 "ultra::individual");
102
103 return it;
104 }
105
106 throw std::format_error("invalid format specifier for ultra::individual");
107 }
108
109 template<class FormatContext>
110 [[nodiscard]] auto format(const ultra::individual &ind,
111 FormatContext &ctx) const
112 {
113 const auto s(ind.format(fmt_));
114 return std::ranges::copy(s, ctx.out()).out;
115 }
116};
117
118template<std::derived_from<ultra::individual> T>
119struct formatter<T, char> : formatter<ultra::individual, char>
120{
121};
122
123} // namespace std
124
125#endif // include guard
Definition individual.h:54
std::string format(out::print_format_t) const
Definition individual.cc:140
print_format_t
Rendering format used to print an individual.
Definition individual.h:29
std::ostream & python_language(std::ostream &o)
Definition individual_format.cc:81
std::ostream & tree(std::ostream &o)
Definition individual_format.cc:155
print_format_t print_format_flag(std::ostream &o)
Definition individual_format.cc:40
std::ostream & graphviz(std::ostream &o)
Definition individual_format.cc:111
std::ostream & dump(std::ostream &o)
Definition individual_format.cc:96
std::ostream & list(std::ostream &o)
Definition individual_format.cc:143
std::ostream & cpp_language(std::ostream &o)
Definition individual_format.cc:69
std::ostream & c_language(std::ostream &o)
Definition individual_format.cc:57
std::ostream & in_line(std::ostream &o)
Definition individual_format.cc:125
STL namespace.