arg_router  1.4.0
C++ command line argument parsing and routing
parsing.hpp
1 // Copyright (C) 2022-2023 by Camden Mannett.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
4 
5 #pragma once
6 
7 #include "arg_router/algorithm.hpp"
8 #include "arg_router/traits.hpp"
9 #include "arg_router/utility/result.hpp"
10 
12 namespace arg_router::parsing
13 {
15 enum class pre_parse_action : std::uint8_t {
17  skip_node,
19  valid_node,
24 };
25 
28 
35 template <typename T>
36 [[nodiscard]] constexpr bool match(token_type token) noexcept
37 {
38  using namespace std::string_literals;
39 
40  if constexpr (traits::has_long_name_method_v<T>) {
41  if ((token.prefix == prefix_type::long_) && (token.name == T::long_name())) {
42  return true;
43  }
44  }
45  if constexpr (traits::has_short_name_method_v<T>) {
46  if ((token.prefix == prefix_type::short_) && (token.name == T::short_name())) {
47  return true;
48  }
49  }
50  if constexpr (traits::has_none_name_method_v<T>) {
51  if ((token.prefix == prefix_type::none) && (token.name == T::none_name())) {
52  return true;
53  }
54  }
55 
56  return false;
57 }
58 
67 template <typename Node>
68 [[nodiscard]] constexpr token_type node_token_type() noexcept
69 {
70  if constexpr (traits::has_error_name_method_v<Node>) {
71  return {prefix_type::none, Node::error_name()};
72  } else if constexpr (traits::has_display_name_method_v<Node>) {
73  return {prefix_type::none, Node::display_name()};
74  } else if constexpr (traits::has_long_name_method_v<Node>) {
75  return {prefix_type::long_, Node::long_name()};
76  } else if constexpr (traits::has_short_name_method_v<Node>) {
77  return {prefix_type::short_, Node::short_name()};
78  } else if constexpr (traits::has_none_name_method_v<Node>) {
79  return {prefix_type::none, Node::none_name()};
80  } else {
81  static_assert(traits::always_false_v<Node>, "Node does not have a name");
82  }
83 }
84 
104 template <typename BaseNode, typename... DerivedAndParents>
105 [[nodiscard]] constexpr auto clean_node_ancestry_list(
106  const BaseNode& base_node,
107  const DerivedAndParents&... derived_and_parents)
108 {
109  // Iterate along the ancestry until you hit a node type that is _not_ a base of Node, then
110  // remove the elements up to that element
111  using parents_tuple = std::tuple<std::decay_t<DerivedAndParents>...>;
112 
113  constexpr auto remove_n = boost::mp11::mp_find_if_q<
114  parents_tuple,
115  boost::mp11::mp_not_fn_q<
116  boost::mp11::mp_bind<std::is_base_of, std::decay_t<BaseNode>, boost::mp11::_1>>>::value;
117  if constexpr (remove_n == 0) {
118  return std::tuple{std::cref(base_node), std::cref(derived_and_parents)...};
119  } else {
120  return algorithm::tuple_drop<remove_n - 1>(std::tuple{std::cref(derived_and_parents)...});
121  }
122 }
123 
132 template <typename Node, typename... Parents>
133 [[nodiscard]] bool is_runtime_disabled(const Node& node, const Parents&... parents) noexcept
134 {
135  auto any_disabled = false;
137  [&]([[maybe_unused]] auto i, auto entry) {
138  using entry_type = typename std::decay_t<decltype(entry)>::type;
139 
140  if constexpr (traits::has_runtime_enabled_method_v<entry_type>) {
141  any_disabled = any_disabled || !entry.get().runtime_enabled();
142  }
143  },
144  std::tuple{std::cref(node), std::cref(parents)...});
145 
146  return any_disabled;
147 }
148 } // namespace arg_router::parsing
constexpr auto tuple_drop(Tuple &&input)
Definition: algorithm.hpp:272
bool is_runtime_disabled(const Node &node, const Parents &... parents) noexcept
Definition: parsing.hpp:133
constexpr token_type node_token_type() noexcept
Definition: parsing.hpp:68
constexpr bool match(token_type token) noexcept
Definition: parsing.hpp:36
constexpr auto clean_node_ancestry_list(const BaseNode &base_node, const DerivedAndParents &... derived_and_parents)
Definition: parsing.hpp:105
constexpr std::enable_if_t< traits::is_tuple_like_v< std::decay_t< Tuple > > > tuple_iterator(F &&f, Tuple &&tuple)