koutil
Loading...
Searching...
No Matches
arg.h
Go to the documentation of this file.
1#ifndef KOUTIL_ARGPARSER_ARG_H
2#define KOUTIL_ARGPARSER_ARG_H
3
4#include <array>
5#include <cassert>
6#include <cstddef>
7#include <ranges>
8#include <span>
9#include <string_view>
10#include <type_traits>
11#include <utility>
12
14
15struct Arg;
16
23template <typename T>
24concept is_arg = std::is_same_v<Arg, std::decay_t<T>>;
25
29struct Arg {
34
35 const char short_name;
36 const std::string_view long_name;
37 const std::string_view description;
38
46 static constexpr Arg option_flag(char opt, std::string_view desc) {
47 assert(opt != '\0');
48 return { OPTION_FLAG, opt, "", desc };
49 }
50
58 static constexpr Arg option_flag(std::string_view long_name, std::string_view desc) {
59 assert(!long_name.empty());
60 return { OPTION_FLAG, '\0', long_name, desc };
61 }
62
71 static constexpr Arg option_flag(char opt, std::string_view long_name, std::string_view desc) {
72 assert(opt != '\0' && !long_name.empty());
73 return { OPTION_FLAG, opt, long_name, desc };
74 }
75
83 static constexpr Arg option_value(std::string_view long_name, std::string_view desc) {
84 assert(!long_name.empty());
85 return { OPTION_VALUE, '\0', long_name, desc };
86 }
87
88 constexpr bool operator==(const Arg& other) const {
89 return short_name == other.short_name && long_name == other.long_name && description == other.description;
90 }
91
92 constexpr bool operator<(char name) const { return short_name < name; }
93
94 constexpr bool operator<(std::string_view name) const { return long_name < name; }
95
96 constexpr bool operator>(char name) const { return short_name > name; }
97
98 constexpr bool operator>(std::string_view name) const { return long_name > name; }
99
100 constexpr bool operator==(char name) const { return short_name == name; }
101
102 constexpr bool operator==(std::string_view name) const { return long_name == name; }
103
104private:
105 constexpr Arg(Type arg_type, char sname, std::string_view lname, std::string_view desc)
106 : type(arg_type)
107 , short_name(sname)
108 , long_name(lname)
109 , description(desc) { }
110};
111
113public:
114 constexpr virtual ~ArgumentsBase() = default;
115 [[nodiscard]] constexpr virtual std::size_t size() const = 0;
116 [[nodiscard]] constexpr virtual std::size_t count_short_args() const = 0;
117 [[nodiscard]] constexpr virtual std::size_t count_long_args() const = 0;
118 [[nodiscard]] constexpr virtual const Arg* find_short(char name) const = 0;
119 [[nodiscard]] constexpr virtual const Arg* find_long(std::string_view name) const = 0;
120 [[nodiscard]] constexpr virtual std::span<const Arg> args() const = 0;
121};
122
129template <typename T>
130concept are_arguments = std::is_base_of_v<ArgumentsBase, T>;
131
135template <is_arg... Args> class Arguments : public ArgumentsBase {
136private:
137 using args_t = std::array<Arg, sizeof...(Args)>;
138 using args_ref_t = std::pair<std::size_t, std::array<std::size_t, sizeof...(Args)>>;
139
140public:
141 constexpr Arguments(const Args&... args)
142 : m_args({ (std::forward<decltype(args)>(args))... }) {
143 create_refs();
144
147 }
148
149 ~Arguments() override = default;
150
156 [[nodiscard]] constexpr std::size_t size() const override { return sizeof...(Args); }
157
163 [[nodiscard]] constexpr std::size_t count_short_args() const override { return m_short_args.first; }
164
170 [[nodiscard]] constexpr std::size_t count_long_args() const override { return m_long_args.first; }
171
178 [[nodiscard]] constexpr const Arg* find_short(char name) const override {
179
180 std::span view(m_short_args.second.begin(), m_short_args.first);
181 for (auto i : view) {
182 if (m_args[i].short_name == name) {
183 return &m_args[i];
184 }
185 }
186
187 return nullptr;
188 }
189
196 [[nodiscard]] constexpr const Arg* find_long(std::string_view name) const override {
197
198 std::span view(m_long_args.second.begin(), m_long_args.first);
199 for (auto i : view) {
200 if (m_args[i].long_name == name) {
201 return &m_args[i];
202 }
203 }
204
205 return nullptr;
206 }
207
213 [[nodiscard]] constexpr std::span<const Arg> args() const override { return m_args; }
214
215private:
219
220 constexpr void create_refs() {
221 for (std::size_t i = 0; i < m_args.size(); ++i) {
222 auto& arg = m_args[i];
223
224 if (arg.short_name != '\0') {
225 m_short_args.second[m_short_args.first++] = i;
226 } else if (!arg.long_name.empty()) {
227 m_long_args.second[m_long_args.first++] = i;
228 } else {
229 assert(false);
230 }
231 }
232 }
233
242 template <typename Proj> constexpr bool contains_duplicates(const args_ref_t& search, Proj member) {
243 std::span view(search.second.begin(), search.first);
244
245 for (auto it = view.begin(); it != view.end(); ++it) {
246 const auto& arg = m_args[*it];
247
248 for (auto it2 = it + 1; it2 != view.end(); ++it2) {
249 const auto& other = m_args[*it2];
250
251 if (arg.*member == other.*member) {
252 return true;
253 }
254 }
255 }
256
257 return false;
258 }
259};
260
261}
262
263#endif
virtual constexpr std::span< const Arg > args() const =0
virtual constexpr const Arg * find_short(char name) const =0
virtual constexpr std::size_t size() const =0
virtual constexpr const Arg * find_long(std::string_view name) const =0
virtual constexpr std::size_t count_short_args() const =0
virtual constexpr std::size_t count_long_args() const =0
virtual constexpr ~ArgumentsBase()=default
Base class for argument collections.
Definition arg.h:135
constexpr const Arg * find_long(std::string_view name) const override
Finds an argument by its long name.
Definition arg.h:196
args_ref_t m_long_args
Definition arg.h:218
constexpr std::size_t size() const override
Gets the number of arguments.
Definition arg.h:156
args_ref_t m_short_args
Definition arg.h:217
constexpr std::size_t count_long_args() const override
Gets the number of long arguments.
Definition arg.h:170
std::pair< std::size_t, std::array< std::size_t, sizeof...(Args)> > args_ref_t
Definition arg.h:138
~Arguments() override=default
std::array< Arg, sizeof...(Args)> args_t
Definition arg.h:137
constexpr bool contains_duplicates(const args_ref_t &search, Proj member)
Checks if there are duplicate arguments.
Definition arg.h:242
constexpr void create_refs()
Definition arg.h:220
args_t m_args
Definition arg.h:216
constexpr const Arg * find_short(char name) const override
Finds an argument by its short name.
Definition arg.h:178
constexpr Arguments(const Args &... args)
Definition arg.h:141
constexpr std::size_t count_short_args() const override
Gets the number of short arguments.
Definition arg.h:163
constexpr std::span< const Arg > args() const override
Gets a span of all arguments.
Definition arg.h:213
Checks if a type is derived from ArgumentsBase.
Definition arg.h:130
Checks if a type is Arg.
Definition arg.h:24
Definition arg.h:13
Base structure representing a subcommand argument.
Definition arg.h:29
constexpr bool operator==(const Arg &other) const
Definition arg.h:88
static constexpr Arg option_value(std::string_view long_name, std::string_view desc)
Constructs an argument of type OPTION_VALUE with a long name and description.
Definition arg.h:83
constexpr bool operator==(char name) const
Definition arg.h:100
const std::string_view long_name
Definition arg.h:36
constexpr Arg(Type arg_type, char sname, std::string_view lname, std::string_view desc)
Definition arg.h:105
constexpr bool operator>(char name) const
Definition arg.h:96
enum koutil::argparser::Arg::Type type
const char short_name
Definition arg.h:35
const std::string_view description
Definition arg.h:37
constexpr bool operator==(std::string_view name) const
Definition arg.h:102
constexpr bool operator>(std::string_view name) const
Definition arg.h:98
static constexpr Arg option_flag(char opt, std::string_view long_name, std::string_view desc)
Constructs an argument of type OPTION_FLAG with both short and long names and a description.
Definition arg.h:71
static constexpr Arg option_flag(std::string_view long_name, std::string_view desc)
Constructs an argument of type OPTION_FLAG with a long name and description.
Definition arg.h:58
constexpr bool operator<(char name) const
Definition arg.h:92
Type
Definition arg.h:30
@ OPTION_FLAG
Definition arg.h:31
@ OPTION_VALUE
Definition arg.h:32
constexpr bool operator<(std::string_view name) const
Definition arg.h:94
static constexpr Arg option_flag(char opt, std::string_view desc)
Constructs an argument of type OPTION_FLAG with a short name and description.
Definition arg.h:46