CLI11
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
StringTools.hpp
1// Copyright (c) 2017-2024, 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// IWYU pragma: private, include "CLI/CLI.hpp"
10
11// [CLI11:public_includes:set]
12#include <algorithm>
13#include <iomanip>
14#include <locale>
15#include <sstream>
16#include <stdexcept>
17#include <string>
18#include <type_traits>
19#include <vector>
20// [CLI11:public_includes:end]
21
22#include "Macros.hpp"
23
24namespace CLI {
25
26// [CLI11:string_tools_hpp:verbatim]
27
30namespace enums {
31
33template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
34std::ostream &operator<<(std::ostream &in, const T &item) {
35 // make sure this is out of the detail namespace otherwise it won't be found when needed
36 return in << static_cast<typename std::underlying_type<T>::type>(item);
37}
38
39} // namespace enums
40
42using enums::operator<<;
43
44namespace detail {
47constexpr int expected_max_vector_size{1 << 29};
48// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
50CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim);
51
53template <typename T> std::string join(const T &v, std::string delim = ",") {
54 std::ostringstream s;
55 auto beg = std::begin(v);
56 auto end = std::end(v);
57 if(beg != end)
58 s << *beg++;
59 while(beg != end) {
60 s << delim << *beg++;
61 }
62 return s.str();
63}
64
66template <typename T,
67 typename Callable,
68 typename = typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
69std::string join(const T &v, Callable func, std::string delim = ",") {
70 std::ostringstream s;
71 auto beg = std::begin(v);
72 auto end = std::end(v);
73 auto loc = s.tellp();
74 while(beg != end) {
75 auto nloc = s.tellp();
76 if(nloc > loc) {
77 s << delim;
78 loc = nloc;
79 }
80 s << func(*beg++);
81 }
82 return s.str();
83}
84
86template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
87 std::ostringstream s;
88 for(std::size_t start = 0; start < v.size(); start++) {
89 if(start > 0)
90 s << delim;
91 s << v[v.size() - start - 1];
92 }
93 return s.str();
94}
95
96// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
97
99CLI11_INLINE std::string &ltrim(std::string &str);
100
102CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter);
103
105CLI11_INLINE std::string &rtrim(std::string &str);
106
108CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter);
109
111inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
112
114inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
115
117inline std::string trim_copy(const std::string &str) {
118 std::string s = str;
119 return trim(s);
120}
121
123CLI11_INLINE std::string &remove_quotes(std::string &str);
124
126CLI11_INLINE void remove_quotes(std::vector<std::string> &args);
127
132CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input);
133
135inline std::string trim_copy(const std::string &str, const std::string &filter) {
136 std::string s = str;
137 return trim(s, filter);
138}
140CLI11_INLINE std::ostream &
141format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid);
142
144CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
145
148template <typename T> bool valid_first_char(T c) {
149 return ((c != '-') && (static_cast<unsigned char>(c) > 33)); // space and '!' not allowed
150}
151
153template <typename T> bool valid_later_char(T c) {
154 // = and : are value separators, { has special meaning for option defaults,
155 // and control codes other than tab would just be annoying to deal with in many places allowing space here has too
156 // much potential for inadvertent entry errors and bugs
157 return ((c != '=') && (c != ':') && (c != '{') && ((static_cast<unsigned char>(c) > 32) || c == '\t'));
158}
159
161CLI11_INLINE bool valid_name_string(const std::string &str);
162
164inline bool valid_alias_name_string(const std::string &str) {
165 static const std::string badChars(std::string("\n") + '\0');
166 return (str.find_first_of(badChars) == std::string::npos);
167}
168
170inline bool is_separator(const std::string &str) {
171 static const std::string sep("%%");
172 return (str.empty() || str == sep);
173}
174
176inline bool isalpha(const std::string &str) {
177 return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); });
178}
179
181inline std::string to_lower(std::string str) {
182 std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
183 return std::tolower(x, std::locale());
184 });
185 return str;
186}
187
189inline std::string remove_underscore(std::string str) {
190 str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
191 return str;
192}
193
195CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to);
196
198inline bool has_default_flag_values(const std::string &flags) {
199 return (flags.find_first_of("{!") != std::string::npos);
200}
201
202CLI11_INLINE void remove_default_flag_values(std::string &flags);
203
205CLI11_INLINE std::ptrdiff_t find_member(std::string name,
206 const std::vector<std::string> names,
207 bool ignore_case = false,
208 bool ignore_underscore = false);
209
212template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
213 std::size_t start_pos = 0;
214 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
215 start_pos = modify(str, start_pos);
216 }
217 return str;
218}
219
222CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char);
223
226CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
227
229CLI11_INLINE std::string get_environment_value(const std::string &env_name);
230
235CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
236
240CLI11_INLINE bool has_escapable_character(const std::string &str);
241
245CLI11_INLINE std::string add_escaped_characters(const std::string &str);
246
248CLI11_INLINE std::string remove_escaped_characters(const std::string &str);
249
251CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape);
252
253CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string);
254
256CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string);
257
259CLI11_INLINE bool process_quoted_string(std::string &str, char string_char = '\"', char literal_char = '\'');
260
261} // namespace detail
262
263// [CLI11:string_tools_hpp:end]
264
265} // namespace CLI
266
267#ifndef CLI11_COMPILE
268#include "impl/StringTools_inl.hpp" // IWYU pragma: export
269#endif