CLI11
C++11 Command Line Interface Parser
Loading...
Searching...
No Matches
StringTools.hpp
1// Copyright (c) 2017-2025, 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 // https://isocpp.org/wiki/faq/input-output#print-char-or-ptr-as-number
37 return in << +static_cast<typename std::underlying_type<T>::type>(item);
38}
39
40} // namespace enums
41
43using enums::operator<<;
44
45namespace detail {
48constexpr int expected_max_vector_size{1 << 29};
49// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
51CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim);
52
54template <typename T> std::string join(const T &v, std::string delim = ",") {
55 std::ostringstream s;
56 auto beg = std::begin(v);
57 auto end = std::end(v);
58 if(beg != end)
59 s << *beg++;
60 while(beg != end) {
61 s << delim << *beg++;
62 }
63 auto rval = s.str();
64 if(!rval.empty() && delim.size() == 1 && rval.back() == delim[0]) {
65 // remove trailing delimiter if the last entry was empty
66 rval.pop_back();
67 }
68 return rval;
69}
70
72template <typename T,
73 typename Callable,
74 typename = typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
75std::string join(const T &v, Callable func, std::string delim = ",") {
76 std::ostringstream s;
77 auto beg = std::begin(v);
78 auto end = std::end(v);
79 auto loc = s.tellp();
80 while(beg != end) {
81 auto nloc = s.tellp();
82 if(nloc > loc) {
83 s << delim;
84 loc = nloc;
85 }
86 s << func(*beg++);
87 }
88 return s.str();
89}
90
92template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
93 std::ostringstream s;
94 for(std::size_t start = 0; start < v.size(); start++) {
95 if(start > 0)
96 s << delim;
97 s << v[v.size() - start - 1];
98 }
99 return s.str();
100}
101
102// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
103
105CLI11_INLINE std::string &ltrim(std::string &str);
106
108CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter);
109
111CLI11_INLINE std::string &rtrim(std::string &str);
112
114CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter);
115
117inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
118
120inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
121
123inline std::string trim_copy(const std::string &str) {
124 std::string s = str;
125 return trim(s);
126}
127
129CLI11_INLINE std::string &remove_quotes(std::string &str);
130
132CLI11_INLINE void remove_quotes(std::vector<std::string> &args);
133
138CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input);
139
141inline std::string trim_copy(const std::string &str, const std::string &filter) {
142 std::string s = str;
143 return trim(s, filter);
144}
145
147CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
148
151template <typename T> bool valid_first_char(T c) {
152 return ((c != '-') && (static_cast<unsigned char>(c) > 33)); // space and '!' not allowed
153}
154
156template <typename T> bool valid_later_char(T c) {
157 // = and : are value separators, { has special meaning for option defaults,
158 // and control codes other than tab would just be annoying to deal with in many places allowing space here has too
159 // much potential for inadvertent entry errors and bugs
160 return ((c != '=') && (c != ':') && (c != '{') && ((static_cast<unsigned char>(c) > 32) || c == '\t'));
161}
162
164CLI11_INLINE bool valid_name_string(const std::string &str);
165
167inline bool valid_alias_name_string(const std::string &str) {
168 static const std::string badChars(std::string("\n") + '\0');
169 return (str.find_first_of(badChars) == std::string::npos);
170}
171
173inline bool is_separator(const std::string &str) {
174 static const std::string sep("%%");
175 return (str.empty() || str == sep);
176}
177
179inline bool isalpha(const std::string &str) {
180 return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); });
181}
182
184inline std::string to_lower(std::string str) {
185 std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
186 return std::tolower(x, std::locale());
187 });
188 return str;
189}
190
192inline std::string remove_underscore(std::string str) {
193 str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
194 return str;
195}
196
198CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to);
199
201inline bool has_default_flag_values(const std::string &flags) {
202 return (flags.find_first_of("{!") != std::string::npos);
203}
204
205CLI11_INLINE void remove_default_flag_values(std::string &flags);
206
208CLI11_INLINE std::ptrdiff_t find_member(std::string name,
209 const std::vector<std::string> names,
210 bool ignore_case = false,
211 bool ignore_underscore = false);
212
215template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
216 std::size_t start_pos = 0;
217 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
218 start_pos = modify(str, start_pos);
219 }
220 return str;
221}
222
225CLI11_INLINE std::size_t close_sequence(const std::string &str, std::size_t start, char closure_char);
226
229CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
230
232CLI11_INLINE std::string get_environment_value(const std::string &env_name);
233
238CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
239
243CLI11_INLINE bool has_escapable_character(const std::string &str);
244
248CLI11_INLINE std::string add_escaped_characters(const std::string &str);
249
251CLI11_INLINE std::string remove_escaped_characters(const std::string &str);
252
254CLI11_INLINE std::string binary_escape_string(const std::string &string_to_escape);
255
256CLI11_INLINE bool is_binary_escaped_string(const std::string &escaped_string);
257
259CLI11_INLINE std::string extract_binary_string(const std::string &escaped_string);
260
262CLI11_INLINE bool process_quoted_string(std::string &str, char string_char = '\"', char literal_char = '\'');
263
266CLI11_INLINE std::ostream &streamOutAsParagraph(std::ostream &out,
267 const std::string &text,
268 std::size_t paragraphWidth,
269 const std::string &linePrefix = "",
270 bool skipPrefixOnFirstLine = false);
271
272} // namespace detail
273
274// [CLI11:string_tools_hpp:end]
275
276} // namespace CLI
277
278#ifndef CLI11_COMPILE
279#include "impl/StringTools_inl.hpp" // IWYU pragma: export
280#endif
std::ostream & operator<<(std::ostream &in, const T &item)
output streaming for enumerations
Definition StringTools.hpp:34