C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
option.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "../../abi/string.hpp"
26#include "../../meta/fingerprint.hpp"
27#include "../common_types.hpp"
28#include "../validation_result.hpp"
29
30#include <array>
31#include <concepts>
32#include <memory>
33#include <optional>
34#include <span>
35#include <string_view>
36#include <type_traits>
37#include <utility>
38
39namespace essence::cli::abstract {
44 class option {
45 public:
46 template <typename T>
47 requires(!std::same_as<std::decay_t<T>, option>)
48 explicit option(T&& value) : wrapper_{std::make_shared<wrapper<T>>(std::forward<T>(value))} {}
49
50 [[nodiscard]] abi::string bound_name() const {
51 return wrapper_->bound_name();
52 }
53
54 const option& set_bound_name(std::string_view name) const { // NOLINT(*-use-nodiscard)
55 wrapper_->set_bound_name(name);
56
57 return *this;
58 }
59
60 [[nodiscard]] abi::string description() const {
61 return wrapper_->description();
62 }
63
64 [[nodiscard]] const option& set_description(std::string_view description) const {
65 wrapper_->set_description(description);
66
67 return *this;
68 }
69
70 [[nodiscard]] std::span<const abi::string> aliases() const {
71 return wrapper_->aliases();
72 }
73
74 const option& add_aliases(std::span<const abi::string> aliases) const { // NOLINT(*-use-nodiscard)
75 wrapper_->add_aliases(aliases);
76
77 return *this;
78 }
79
80 [[nodiscard]] std::optional<abi::string> default_value_str() const {
81 return wrapper_->default_value_str();
82 }
83
84 [[nodiscard]] std::span<const abi::string> valid_value_strs() const {
85 return wrapper_->valid_value_strs();
86 }
87
88 [[nodiscard]] abi::string name_hints() const {
89 return wrapper_->name_hints();
90 }
91
92 [[nodiscard]] abi::string value_hints() const {
93 return wrapper_->value_hints();
94 }
95
96 [[nodiscard]] bool check_target_type(meta::fingerprint id) const {
97 return wrapper_->check_target_type(id);
98 }
99
100 [[nodiscard]] bool parse_value_and_cache(std::string_view value) const {
101 return wrapper_->parse_value_and_cache(value);
102 }
103
104 void validate(std::string_view value, validation_result& result) const {
105 wrapper_->validate(value, result);
106 }
107
108 void raise_error(std::string_view message) const {
109 wrapper_->raise_error(message);
110 }
111
112 [[nodiscard]] void* underlying_ptr() const noexcept {
113 return wrapper_.get();
114 }
115
116 void on_validation(const validation_handler& handler) const {
117 wrapper_->on_validation(handler);
118 }
119
120 void on_error(const output_handler& handler) const {
121 wrapper_->on_error(handler);
122 }
123
124 template <std::convertible_to<std::string_view>... Args>
125 const option& add_aliases(Args&&... args) const {
126 return add_aliases(std::array{abi::string{std::string_view{std::forward<Args>(args)...}}});
127 }
128
129 template <typename T>
130 void set_target_from_cache(T& target) const {
131 static constexpr meta::fingerprint id{std::type_identity<T>{}};
132
133 if (check_target_type(id)) {
134 wrapper_->set_target_from_cache(&target);
135 }
136 }
137
138 private:
139 struct base {
140 virtual ~base() = default;
141 virtual abi::string bound_name() = 0;
142 virtual void set_bound_name(std::string_view name) = 0;
143 virtual abi::string description() = 0;
144 virtual void set_description(std::string_view description) = 0;
145 virtual std::span<const abi::string> aliases() = 0;
146 virtual void add_aliases(std::span<const abi::string> aliases) = 0;
147 virtual std::optional<abi::string> default_value_str() = 0;
148 virtual std::span<const abi::string> valid_value_strs() = 0;
149 virtual abi::string name_hints() = 0;
150 virtual abi::string value_hints() = 0;
151 virtual bool check_target_type(meta::fingerprint id) = 0;
152 virtual bool parse_value_and_cache(std::string_view value) = 0;
153 virtual void set_target_from_cache(void* target) = 0;
154 virtual void validate(std::string_view value, validation_result& result) = 0;
155 virtual void raise_error(std::string_view message) = 0;
156 virtual void on_validation(const validation_handler& handler) = 0;
157 virtual void on_error(const output_handler& handler) = 0;
158 };
159
160 template <typename T>
161 class wrapper final : public base {
162 public:
163 template <std::convertible_to<T> U>
164 explicit wrapper(U&& value) : value_{std::forward<U>(value)} {}
165
166 abi::string bound_name() override {
167 return value_.bound_name();
168 }
169
170 void set_bound_name(std::string_view name) override {
171 value_.set_bound_name(name);
172 }
173
174 abi::string description() override {
175 return value_.description();
176 }
177
178 void set_description(std::string_view description) override {
179 value_.set_description(description);
180 }
181
182 std::span<const abi::string> aliases() override {
183 return value_.aliases();
184 }
185
186 void add_aliases(std::span<const abi::string> aliases) override {
187 value_.add_aliases(aliases);
188 }
189
190 std::optional<abi::string> default_value_str() override {
191 return value_.default_value_str();
192 }
193
194 std::span<const abi::string> valid_value_strs() override {
195 return value_.valid_value_strs();
196 }
197
198 abi::string name_hints() override {
199 return value_.name_hints();
200 }
201
202 abi::string value_hints() override {
203 return value_.value_hints();
204 }
205
206 bool check_target_type(meta::fingerprint id) override {
207 return value_.check_target_type(id);
208 }
209
210 bool parse_value_and_cache(std::string_view value) override {
211 return value_.parse_value_and_cache(value);
212 }
213
214 void set_target_from_cache(void* target) override {
215 value_.set_target_from_cache(target);
216 }
217
218 void validate(std::string_view value, validation_result& result) override {
219 value_.validate(value, result);
220 }
221
222 void raise_error(std::string_view message) override {
223 value_.raise_error(message);
224 }
225
226 void on_validation(const validation_handler& handler) override {
227 value_.on_validation(handler);
228 }
229
230 void on_error(const output_handler& handler) override {
231 value_.on_error(handler);
232 }
233
234 private:
235 T value_;
236 };
237
238 std::shared_ptr<base> wrapper_;
239 };
240} // namespace essence::cli::abstract
A CLI option, i.e. –xxx=yyy.
Definition option.hpp:44
A unique identifier of a type, i.e. a fingerprint.
Definition fingerprint.hpp:34
The validation result from parsing a CLI option.
Definition validation_result.hpp:34