CLI11  2.1.2
Split.hpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
2 // under NSF AWARD 1414736 and by the respective contributors.
3 // All rights reserved.
4 //
5 // SPDX-License-Identifier: BSD-3-Clause
6 
7 #pragma once
8 
9 // [CLI11:public_includes:set]
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 // [CLI11:public_includes:end]
15 
16 #include "Error.hpp"
17 #include "StringTools.hpp"
18 
19 namespace CLI {
20 // [CLI11:split_hpp:verbatim]
21 
22 namespace detail {
23 
24 // Returns false if not a short option. Otherwise, sets opt name and rest and returns true
25 inline bool split_short(const std::string &current, std::string &name, std::string &rest) {
26  if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) {
27  name = current.substr(1, 1);
28  rest = current.substr(2);
29  return true;
30  }
31  return false;
32 }
33 
34 // Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
35 inline bool split_long(const std::string &current, std::string &name, std::string &value) {
36  if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) {
37  auto loc = current.find_first_of('=');
38  if(loc != std::string::npos) {
39  name = current.substr(2, loc - 2);
40  value = current.substr(loc + 1);
41  } else {
42  name = current.substr(2);
43  value = "";
44  }
45  return true;
46  }
47  return false;
48 }
49 
50 // Returns false if not a windows style option. Otherwise, sets opt name and value and returns true
51 inline bool split_windows_style(const std::string &current, std::string &name, std::string &value) {
52  if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) {
53  auto loc = current.find_first_of(':');
54  if(loc != std::string::npos) {
55  name = current.substr(1, loc - 1);
56  value = current.substr(loc + 1);
57  } else {
58  name = current.substr(1);
59  value = "";
60  }
61  return true;
62  }
63  return false;
64 }
65 
66 // Splits a string into multiple long and short names
67 inline std::vector<std::string> split_names(std::string current) {
68  std::vector<std::string> output;
69  std::size_t val;
70  while((val = current.find(",")) != std::string::npos) {
71  output.push_back(trim_copy(current.substr(0, val)));
72  current = current.substr(val + 1);
73  }
74  output.push_back(trim_copy(current));
75  return output;
76 }
77 
79 inline std::vector<std::pair<std::string, std::string>> get_default_flag_values(const std::string &str) {
80  std::vector<std::string> flags = split_names(str);
81  flags.erase(std::remove_if(flags.begin(),
82  flags.end(),
83  [](const std::string &name) {
84  return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) &&
85  (name.back() == '}')) ||
86  (name[0] == '!'))));
87  }),
88  flags.end());
89  std::vector<std::pair<std::string, std::string>> output;
90  output.reserve(flags.size());
91  for(auto &flag : flags) {
92  auto def_start = flag.find_first_of('{');
93  std::string defval = "false";
94  if((def_start != std::string::npos) && (flag.back() == '}')) {
95  defval = flag.substr(def_start + 1);
96  defval.pop_back();
97  flag.erase(def_start, std::string::npos);
98  }
99  flag.erase(0, flag.find_first_not_of("-!"));
100  output.emplace_back(flag, defval);
101  }
102  return output;
103 }
104 
106 inline std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
107 get_names(const std::vector<std::string> &input) {
108 
109  std::vector<std::string> short_names;
110  std::vector<std::string> long_names;
111  std::string pos_name;
112 
113  for(std::string name : input) {
114  if(name.length() == 0) {
115  continue;
116  }
117  if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
118  if(name.length() == 2 && valid_first_char(name[1]))
119  short_names.emplace_back(1, name[1]);
120  else
121  throw BadNameString::OneCharName(name);
122  } else if(name.length() > 2 && name.substr(0, 2) == "--") {
123  name = name.substr(2);
124  if(valid_name_string(name))
125  long_names.push_back(name);
126  else
127  throw BadNameString::BadLongName(name);
128  } else if(name == "-" || name == "--") {
129  throw BadNameString::DashesOnly(name);
130  } else {
131  if(pos_name.length() > 0)
132  throw BadNameString::MultiPositionalNames(name);
133  pos_name = name;
134  }
135  }
136 
137  return std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>(
138  short_names, long_names, pos_name);
139 }
140 
141 } // namespace detail
142 // [CLI11:split_hpp:end]
143 } // namespace CLI
bool split_long(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:35
bool split_short(const std::string &current, std::string &name, std::string &rest)
Definition: Split.hpp:25
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:107
bool valid_first_char(T c)
Definition: StringTools.hpp:219
bool valid_name_string(const std::string &str)
Verify an option/subcommand name.
Definition: StringTools.hpp:230
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:79
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition: StringTools.hpp:144
bool split_windows_style(const std::string &current, std::string &name, std::string &value)
Definition: Split.hpp:51
std::vector< std::string > split_names(std::string current)
Definition: Split.hpp:67
Definition: App.hpp:34