CLI11  2.3.2
StringTools.hpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2023, 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 <algorithm>
11 #include <iomanip>
12 #include <locale>
13 #include <sstream>
14 #include <stdexcept>
15 #include <string>
16 #include <type_traits>
17 #include <vector>
18 // [CLI11:public_includes:end]
19 
20 #include "Macros.hpp"
21 
22 namespace CLI {
23 
24 // [CLI11:string_tools_hpp:verbatim]
25 
28 namespace enums {
29 
31 template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
32 std::ostream &operator<<(std::ostream &in, const T &item) {
33  // make sure this is out of the detail namespace otherwise it won't be found when needed
34  return in << static_cast<typename std::underlying_type<T>::type>(item);
35 }
36 
37 } // namespace enums
38 
40 using enums::operator<<;
41 
42 namespace detail {
45 constexpr int expected_max_vector_size{1 << 29};
46 // Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
48 CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim);
49 
51 template <typename T> std::string join(const T &v, std::string delim = ",") {
52  std::ostringstream s;
53  auto beg = std::begin(v);
54  auto end = std::end(v);
55  if(beg != end)
56  s << *beg++;
57  while(beg != end) {
58  s << delim << *beg++;
59  }
60  return s.str();
61 }
62 
64 template <typename T,
65  typename Callable,
66  typename = typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
67 std::string join(const T &v, Callable func, std::string delim = ",") {
68  std::ostringstream s;
69  auto beg = std::begin(v);
70  auto end = std::end(v);
71  auto loc = s.tellp();
72  while(beg != end) {
73  auto nloc = s.tellp();
74  if(nloc > loc) {
75  s << delim;
76  loc = nloc;
77  }
78  s << func(*beg++);
79  }
80  return s.str();
81 }
82 
84 template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
85  std::ostringstream s;
86  for(std::size_t start = 0; start < v.size(); start++) {
87  if(start > 0)
88  s << delim;
89  s << v[v.size() - start - 1];
90  }
91  return s.str();
92 }
93 
94 // Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
95 
97 CLI11_INLINE std::string &ltrim(std::string &str);
98 
100 CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter);
101 
103 CLI11_INLINE std::string &rtrim(std::string &str);
104 
106 CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter);
107 
109 inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
110 
112 inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
113 
115 inline std::string trim_copy(const std::string &str) {
116  std::string s = str;
117  return trim(s);
118 }
119 
121 CLI11_INLINE std::string &remove_quotes(std::string &str);
122 
127 CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input);
128 
130 inline std::string trim_copy(const std::string &str, const std::string &filter) {
131  std::string s = str;
132  return trim(s, filter);
133 }
135 CLI11_INLINE std::ostream &
136 format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid);
137 
139 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
140 
143 template <typename T> bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); }
144 
146 template <typename T> bool valid_later_char(T c) {
147  // = and : are value separators, { has special meaning for option defaults,
148  // and \n would just be annoying to deal with in many places allowing space here has too much potential for
149  // inadvertent entry errors and bugs
150  return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n');
151 }
152 
154 CLI11_INLINE bool valid_name_string(const std::string &str);
155 
157 inline bool valid_alias_name_string(const std::string &str) {
158  static const std::string badChars(std::string("\n") + '\0');
159  return (str.find_first_of(badChars) == std::string::npos);
160 }
161 
163 inline bool is_separator(const std::string &str) {
164  static const std::string sep("%%");
165  return (str.empty() || str == sep);
166 }
167 
169 inline bool isalpha(const std::string &str) {
170  return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); });
171 }
172 
174 inline std::string to_lower(std::string str) {
175  std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
176  return std::tolower(x, std::locale());
177  });
178  return str;
179 }
180 
182 inline std::string remove_underscore(std::string str) {
183  str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
184  return str;
185 }
186 
188 CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to);
189 
191 inline bool has_default_flag_values(const std::string &flags) {
192  return (flags.find_first_of("{!") != std::string::npos);
193 }
194 
195 CLI11_INLINE void remove_default_flag_values(std::string &flags);
196 
198 CLI11_INLINE std::ptrdiff_t find_member(std::string name,
199  const std::vector<std::string> names,
200  bool ignore_case = false,
201  bool ignore_underscore = false);
202 
205 template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
206  std::size_t start_pos = 0;
207  while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
208  start_pos = modify(str, start_pos);
209  }
210  return str;
211 }
212 
215 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
216 
221 CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
222 
224 CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
225 
226 } // namespace detail
227 
228 // [CLI11:string_tools_hpp:end]
229 
230 } // namespace CLI
231 
232 #ifndef CLI11_COMPILE
233 #include "impl/StringTools_inl.hpp"
234 #endif
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition: StringTools.hpp:115
CLI11_INLINE std::ostream & format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid)
Print a two part "help" string.
Definition: App.hpp:34
CLI11_INLINE std::string & remove_quotes(std::string &str)
remove quotes at the front and back of a string either &#39;"&#39; or &#39;\&#39;&#39;
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: Validators.hpp:713
bool valid_later_char(T c)
Verify following characters of an option.
Definition: StringTools.hpp:146
bool is_separator(const std::string &str)
check if a string is a container segment separator (empty or "%%")
Definition: StringTools.hpp:163
std::string rjoin(const T &v, std::string delim=",")
Join a string in reverse order.
Definition: StringTools.hpp:84
CLI11_INLINE std::ostream & format_aliases(std::ostream &out, const std::vector< std::string > &aliases, std::size_t wid)
Print subcommand aliases.
CLI11_INLINE bool valid_name_string(const std::string &str)
Verify an option/subcommand name.
CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input)
#define CLI11_INLINE
Definition: Macros.hpp:73
std::ostream & operator<<(std::ostream &in, const T &item)
output streaming for enumerations
Definition: StringTools.hpp:32
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform. ...
Definition: Validators.hpp:716
std::string find_and_modify(std::string str, std::string trigger, Callable modify)
Definition: StringTools.hpp:205
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition: StringTools.hpp:51
std::string & trim(std::string &str)
Trim whitespace from string.
Definition: StringTools.hpp:109
CLI11_INLINE std::string & rtrim(std::string &str)
Trim whitespace from right of string.
std::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:182
CLI11_INLINE std::string & ltrim(std::string &str)
Trim whitespace from left of string.
CLI11_INLINE std::string & add_quotes_if_needed(std::string &str)
Add quotes if the string contains spaces.
CLI11_INLINE std::vector< std::string > split_up(std::string str, char delimiter='\0')
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition: StringTools.hpp:174
CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to)
Find and replace a substring with another substring.
CLI11_INLINE std::ptrdiff_t find_member(std::string name, const std::vector< std::string > names, bool ignore_case=false, bool ignore_underscore=false)
Check if a string is a member of a list of strings and optionally ignore case or ignore underscores...
CLI11_INLINE std::vector< std::string > split(const std::string &s, char delim)
Split a string by a delim.
CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset)
CLI11_INLINE void remove_default_flag_values(std::string &flags)
bool valid_first_char(T c)
Definition: StringTools.hpp:143
bool has_default_flag_values(const std::string &flags)
check if the flag definitions has possible false flags
Definition: StringTools.hpp:191
bool valid_alias_name_string(const std::string &str)
Verify an app name.
Definition: StringTools.hpp:157
constexpr int expected_max_vector_size
Definition: StringTools.hpp:45
bool isalpha(const std::string &str)
Verify that str consists of letters only.
Definition: StringTools.hpp:169