CLI11  1.9.0
Split.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 // Distributed under the 3-Clause BSD License. See accompanying
4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details.
5 
6 #include <string>
7 #include <tuple>
8 #include <vector>
9 
10 #include "CLI/Error.hpp"
11 #include "CLI/StringTools.hpp"
12 
13 namespace CLI {
14 namespace detail {
15 
16 // Returns false if not a short option. Otherwise, sets opt name and rest and returns true
17 inline bool split_short(const std::string &current, std::string &name, std::string &rest) {
18  if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) {
19  name = current.substr(1, 1);
20  rest = current.substr(2);
21  return true;
22  }
23  return false;
24 }
25 
26 // Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
27 inline bool split_long(const std::string &current, std::string &name, std::string &value) {
28  if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) {
29  auto loc = current.find_first_of('=');
30  if(loc != std::string::npos) {
31  name = current.substr(2, loc - 2);
32  value = current.substr(loc + 1);
33  } else {
34  name = current.substr(2);
35  value = "";
36  }
37  return true;
38  }
39  return false;
40 }
41 
42 // Returns false if not a windows style option. Otherwise, sets opt name and value and returns true
43 inline bool split_windows_style(const std::string &current, std::string &name, std::string &value) {
44  if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) {
45  auto loc = current.find_first_of(':');
46  if(loc != std::string::npos) {
47  name = current.substr(1, loc - 1);
48  value = current.substr(loc + 1);
49  } else {
50  name = current.substr(1);
51  value = "";
52  }
53  return true;
54  }
55  return false;
56 }
57 
58 // Splits a string into multiple long and short names
59 inline std::vector<std::string> split_names(std::string current) {
60  std::vector<std::string> output;
61  std::size_t val;
62  while((val = current.find(",")) != std::string::npos) {
63  output.push_back(trim_copy(current.substr(0, val)));
64  current = current.substr(val + 1);
65  }
66  output.push_back(trim_copy(current));
67  return output;
68 }
69 
71 inline std::vector<std::pair<std::string, std::string>> get_default_flag_values(const std::string &str) {
72  std::vector<std::string> flags = split_names(str);
73  flags.erase(std::remove_if(flags.begin(),
74  flags.end(),
75  [](const std::string &name) {
76  return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) &&
77  (name.back() == '}')) ||
78  (name[0] == '!'))));
79  }),
80  flags.end());
81  std::vector<std::pair<std::string, std::string>> output;
82  output.reserve(flags.size());
83  for(auto &flag : flags) {
84  auto def_start = flag.find_first_of('{');
85  std::string defval = "false";
86  if((def_start != std::string::npos) && (flag.back() == '}')) {
87  defval = flag.substr(def_start + 1);
88  defval.pop_back();
89  flag.erase(def_start, std::string::npos);
90  }
91  flag.erase(0, flag.find_first_not_of("-!"));
92  output.emplace_back(flag, defval);
93  }
94  return output;
95 }
96 
98 inline std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
99 get_names(const std::vector<std::string> &input) {
100 
101  std::vector<std::string> short_names;
102  std::vector<std::string> long_names;
103  std::string pos_name;
104 
105  for(std::string name : input) {
106  if(name.length() == 0) {
107  continue;
108  }
109  if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
110  if(name.length() == 2 && valid_first_char(name[1]))
111  short_names.emplace_back(1, name[1]);
112  else
113  throw BadNameString::OneCharName(name);
114  } else if(name.length() > 2 && name.substr(0, 2) == "--") {
115  name = name.substr(2);
116  if(valid_name_string(name))
117  long_names.push_back(name);
118  else
119  throw BadNameString::BadLongName(name);
120  } else if(name == "-" || name == "--") {
121  throw BadNameString::DashesOnly(name);
122  } else {
123  if(pos_name.length() > 0)
124  throw BadNameString::MultiPositionalNames(name);
125  pos_name = name;
126  }
127  }
128 
129  return std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>(
130  short_names, long_names, pos_name);
131 }
132 
133 } // namespace detail
134 } // namespace CLI
CLI::detail::valid_first_char
bool valid_first_char(T c)
Verify the first character of an option.
Definition: StringTools.hpp:173
Error.hpp
CLI::detail::trim_copy
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition: StringTools.hpp:133
CLI::detail::get_default_flag_values
std::vector< std::pair< std::string, std::string > > get_default_flag_values(const std::string &str)
extract default flag values either {def} or starting with a !
Definition: Split.hpp:71
CLI
Definition: App.hpp:27
CLI::detail::valid_name_string
bool valid_name_string(const std::string &str)
Verify an option name.
Definition: StringTools.hpp:181
CLI::detail::split_short
bool split_short(const std::string &current, std::string &name, std::string &rest)
Definition: Split.hpp:17
CLI::detail::get_names
std::tuple< std::vector< std::string >, std::vector< std::string >, std::string > get_names(const std::vector< std::string > &input)
Get a vector of short names, one of long names, and a single name.
Definition: Split.hpp:99
CLI::detail::split_windows_style
bool split_windows_style(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:43
StringTools.hpp
CLI::detail::split_names
std::vector< std::string > split_names(std::string current)
Definition: Split.hpp:59
CLI::detail::split_long
bool split_long(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:27