Motiv
Marvelous OTF2 Traces Interactive Visualizer
Loading...
Searching...
No Matches
Builder.hpp
1/*
2 * Marvelous OTF2 Traces Interactive Visualizer (MOTIV)
3 * Copyright (C) 2023 Florian Gallrein, Björn Gehrke
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#ifndef MOTIV_BUILDER_HPP
19#define MOTIV_BUILDER_HPP
20
21// Makros allowing performing some operation on each element of a list
22// Code from https://github.com/swansontec/map-macro/blob/master/map.h
23#define EVAL0(...) __VA_ARGS__
24#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
25#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
26#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
27#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
28#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
29
30#define MAP_END(...)
31#define MAP_OUT
32#define MAP_COMMA ,
33
34#define MAP_GET_END2() 0, MAP_END
35#define MAP_GET_END1(...) MAP_GET_END2
36#define MAP_GET_END(...) MAP_GET_END1
37#define MAP_NEXT0(test, next, ...) next MAP_OUT
38#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
39#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
40
41#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
42#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
43
44#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
45#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
46
47#define MAP_LIST0(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, peek, __VA_ARGS__)
48#define MAP_LIST1(f, x, peek, ...) f(x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, peek, __VA_ARGS__)
49
53#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
54
59#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
60
61#define BUILDER_CHECK(field) check_ ## field();
62#define BUILDER_DREF(field) *field ## _
63
67#define BUILDER_FIELD(type, name) \
68private: \
69 std::shared_ptr<type> name ## _; \
70 void check_ ## name() { \
71 if(!name ## _) \
72 throw std::invalid_argument("Field '"#name"'must be set!"); } \
73public: \
74 Builder * name(type & s) { \
75 name ## _ = std::make_shared<type>(s); \
76 return this; \
77 } \
78 std::shared_ptr<type> name() { \
79 return name ## _; \
80 }
81
82#define BUILDER_OPTIONAL_FIELD(type, name) \
83private: \
84 std::shared_ptr<type> name ## _; \
85public: \
86 type name() const { return *name ## _; } \
87 Builder * name(type & s) { \
88 name ## _ = std::make_shared<type>(s); \
89 return this; \
90 }
91
111#define BUILDER(type, content, ...) \
112class Builder : public builder<type> { \
113public: \
114 Builder() = default; \
115 type build(){ \
116 MAP(BUILDER_CHECK, __VA_ARGS__) \
117 return {MAP_LIST(BUILDER_DREF, __VA_ARGS__)}; \
118 }; \
119 content \
120};
121
122template<typename T>
123class builder {
124public:
125 virtual ~builder() = default;
126
135 virtual T build() = 0;
136};
137
138#endif //MOTIV_BUILDER_HPP