arg_router  1.4.0
C++ command line argument parsing and routing
value_separator.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/parsing/parse_target.hpp"
8 #include "arg_router/parsing/parsing.hpp"
9 #include "arg_router/policy/policy.hpp"
10 #include "arg_router/utility/compile_time_optional.hpp"
12 
13 namespace arg_router::policy
14 {
30 template <typename S>
32 {
33  static_assert(utility::utf8::count(S::get()) == 1,
34  "Value separator must only be one character");
35  static_assert(!utility::utf8::is_whitespace(S::get()),
36  "Value separator character must not be whitespace");
37 
38 public:
40  using string_type = S;
41 
43  constexpr static auto priority = std::size_t{1000};
44 
49  constexpr explicit value_separator_t([[maybe_unused]] S str = {}) noexcept {}
50 
55  [[nodiscard]] constexpr static std::string_view value_separator() noexcept { return S::get(); }
56 
69  template <typename ProcessedTarget, typename... Parents>
72  [[maybe_unused]] utility::compile_time_optional<ProcessedTarget> processed_target,
73  [[maybe_unused]] parsing::parse_target& target,
74  [[maybe_unused]] const Parents&... parents) const
75  {
76  static_assert((sizeof...(Parents) >= 1),
77  "At least one parent needed for value_separator_t");
78 
79  using owner_type = boost::mp11::mp_first<std::tuple<Parents...>>;
80 
81  static_assert(traits::has_minimum_count_method_v<owner_type> &&
82  traits::has_maximum_count_method_v<owner_type>,
83  "Value separator support requires an owning node to have "
84  "minimum and maximum count policies");
85  static_assert((owner_type::minimum_count() == 1) && (owner_type::maximum_count() == 1),
86  "Value separator support requires an owning node to have "
87  "a fixed count of 1");
88 
89  if (tokens.empty()) {
91  }
92 
93  auto first = tokens.begin();
94  const auto first_token = *first;
95 
96  // Find the separator
97  const auto separator_index = first_token.name.find_first_of(value_separator());
98  if (separator_index == std::string_view::npos) {
99  // If we can't find the separator but the token matches the parent node name, then we
100  // need to throw as the user has just forgotten the separator and needs to be told
101  auto processed_token = first_token;
102  if (first_token.prefix == parsing::prefix_type::none) {
103  processed_token = parsing::get_token_type(first_token.name);
104  }
105  if (parsing::match<owner_type>(processed_token)) {
107  parsing::node_token_type<owner_type>()};
108  }
109 
111  }
112 
113  const auto value_arg = first_token.name.substr(separator_index + S::get().size());
114  if (value_arg.empty()) {
116  }
117 
118  // Insert value token after the label one
119  tokens.insert(first + 1, {parsing::prefix_type::none, value_arg});
120 
121  // Remove the value and separator part of the label token
122  const auto label_arg = first_token.name.substr(0, separator_index);
123  first.set({first_token.prefix, label_arg});
124 
126  }
127 };
128 
133 template <char S>
134 constexpr auto value_separator = value_separator_t<AR_STRING(S)>{};
135 
140 template <typename S>
142 
143 template <typename S>
144 struct is_policy<value_separator_t<S>> : std::true_type {
145 };
146 } // namespace arg_router::policy
iterator insert(iterator it, value_type value)
constexpr static std::string_view value_separator() noexcept
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 value_separator_t([[maybe_unused]] S str={}) noexcept
token_type get_token_type(std::string_view token)
Definition: token_type.hpp:103
constexpr auto value_separator
constexpr auto value_separator_utf8
constexpr bool is_whitespace(std::string_view str) noexcept
Definition: utf8.hpp:289
constexpr std::size_t count(std::string_view str) noexcept
Definition: utf8.hpp:278