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