arg_router  1.4.0
C++ command line argument parsing and routing
min_max_count.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/exception.hpp"
8 #include "arg_router/parsing/parsing.hpp"
9 #include "arg_router/policy/policy.hpp"
10 #include "arg_router/traits.hpp"
11 #include "arg_router/utility/compile_time_optional.hpp"
12 
13 #include <limits>
14 
15 namespace arg_router
16 {
17 namespace policy
18 {
26 template <typename MinType, typename MaxType>
28 {
29  static_assert(traits::has_value_type_v<MinType> && traits::has_value_type_v<MaxType>,
30  "MinType and MaxType must have a value_type");
31  static_assert(std::is_convertible_v<typename MinType::value_type, std::size_t> &&
32  std::is_convertible_v<typename MaxType::value_type, std::size_t>,
33  "MinType and MaxType must have a value_type that is implicitly "
34  "convertible to std::size_t");
35  static_assert(std::is_integral_v<typename MinType::value_type> &&
36  std::is_integral_v<typename MaxType::value_type>,
37  "MinType and MaxType value_types must be integrals");
38  static_assert((MinType::value >= 0) && (MaxType::value >= 0),
39  "MinType and MaxType must have a value that is a positive number");
40  static_assert(MinType::value <= MaxType::value,
41  "MinType must be less than or equal to MaxType");
42 
43 public:
45  constexpr static auto priority = std::size_t{750};
46 
48  [[nodiscard]] constexpr static std::size_t minimum_count() noexcept { return MinType::value; }
49 
51  [[nodiscard]] constexpr static std::size_t maximum_count() noexcept { return MaxType::value; }
52 
71  template <typename ProcessedTarget, typename... Parents>
74  [[maybe_unused]] utility::compile_time_optional<ProcessedTarget> processed_target,
75  [[maybe_unused]] parsing::parse_target& target,
76  [[maybe_unused]] const Parents&... parents) const
77  {
78  static_assert((sizeof...(Parents) >= 1), "At least one parent needed for min_max_count_t");
79 
80  using owner_type = boost::mp11::mp_first<std::tuple<Parents...>>;
81 
82  // The min/max values are for argument counts, and so need adjusting to accomodate the label
83  // tokens
84  constexpr auto named_offset = owner_type::is_named ? 1u : 0u;
85  constexpr auto mn_count = minimum_count() == std::numeric_limits<std::size_t>::max() ?
86  minimum_count() :
87  minimum_count() + named_offset;
88  constexpr auto mx_count = maximum_count() == std::numeric_limits<std::size_t>::max() ?
89  maximum_count() :
90  maximum_count() + named_offset;
91 
92  auto num_tokens = tokens.size();
93  if constexpr (traits::has_token_end_marker_method_v<owner_type>) {
94  // If there's a token end marker attached, then it will have already processed the
95  // tokens as it is a higher priority policy
96  num_tokens = tokens.processed().size();
97 
98  // We can only check that we have exceeded the maximum if there's a token end marker
99  // because know that all the tokens preceding it are for the owner
100  if (num_tokens > mx_count) {
102  parsing::node_token_type<owner_type>()};
103  }
104  }
105 
106  // Check that we are within the minimum bound
107  if (num_tokens < mn_count) {
109  parsing::node_token_type<owner_type>()};
110  }
111 
112  // Transfer any remaining up to the maximum count
113  tokens.transfer(tokens.begin() + std::min(mx_count - 1, num_tokens - 1));
114 
116  }
117 };
118 
124 template <std::size_t MinValue, std::size_t MaxValue>
125 constexpr auto min_max_count =
127 
132 template <std::size_t Value>
133 constexpr auto min_count =
136 
141 template <std::size_t Value>
142 constexpr auto max_count =
144 
149 template <std::size_t Value>
150 constexpr auto fixed_count =
152 
153 template <typename MinType, typename MaxType>
154 struct is_policy<min_max_count_t<MinType, MaxType>> : std::true_type {
155 };
156 } // namespace policy
157 
192 template <std::size_t MinCount, typename... Policies>
194 {
195  template <typename Policy>
196  struct has_min_max_t {
197  constexpr static bool value = traits::has_minimum_count_method_v<Policy> &&
198  traits::has_maximum_count_method_v<Policy>;
199  };
200 
201  using policies_tuple = std::tuple<std::decay_t<Policies>...>;
202  using range_policy_type =
205 
206 public:
210  constexpr static auto has_min_max =
211  boost::mp11::mp_find_if<policies_tuple, has_min_max_t>::value !=
212  std::tuple_size_v<policies_tuple>;
213 
217  using type = std::conditional_t<
218  has_min_max,
219  boost::mp11::mp_rename<policies_tuple, tree_node>,
220  boost::mp11::mp_rename<boost::mp11::mp_push_front<policies_tuple, range_policy_type>,
221  tree_node>>;
222 };
223 } // namespace arg_router
std::conditional_t< has_min_max, boost::mp11::mp_rename< policies_tuple, tree_node >, boost::mp11::mp_rename< boost::mp11::mp_push_front< policies_tuple, range_policy_type >, tree_node > > type
parsing::pre_parse_result pre_parse_phase(parsing::dynamic_token_adapter &tokens, [[maybe_unused]] utility::compile_time_optional< ProcessedTarget > processed_target, [[maybe_unused]] parsing::parse_target &target, [[maybe_unused]] const Parents &... parents) const
constexpr static std::size_t maximum_count() noexcept
constexpr static std::size_t minimum_count() noexcept
constexpr auto max_count
constexpr auto min_max_count
constexpr auto fixed_count
constexpr auto min_count
std::integral_constant< decltype(Value), Value > integral_constant
Definition: traits.hpp:210
@ minimum_count_not_reached
Minimum number of value tokens for node not reached.
@ maximum_count_exceeded
Maximum number of value tokens exceeded.