15 #include <type_traits>
25 template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
26 std::ostream &
operator<<(std::ostream &in,
const T &item) {
28 return in << static_cast<typename std::underlying_type<T>::type>(item);
34 using enums::operator<<;
42 inline std::vector<std::string>
split(
const std::string &s,
char delim) {
43 std::vector<std::string> elems;
51 while(std::getline(ss, item, delim)) {
52 elems.push_back(item);
59 template <
typename T> std::string
join(
const T &v, std::string delim =
",") {
61 auto beg = std::begin(v);
62 auto end = std::end(v);
74 typename =
typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
75 std::string
join(
const T &v, Callable func, std::string delim =
",") {
77 auto beg = std::begin(v);
78 auto end = std::end(v);
82 s << delim << func(*beg++);
88 template <
typename T> std::string
rjoin(
const T &v, std::string delim =
",") {
90 for(std::size_t start = 0; start < v.size(); start++) {
93 s << v[v.size() - start - 1];
101 inline std::string &
ltrim(std::string &str) {
102 auto it = std::find_if(str.begin(), str.end(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
103 str.erase(str.begin(), it);
108 inline std::string &
ltrim(std::string &str,
const std::string &filter) {
109 auto it = std::find_if(str.begin(), str.end(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
110 str.erase(str.begin(), it);
115 inline std::string &
rtrim(std::string &str) {
116 auto it = std::find_if(str.rbegin(), str.rend(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
117 str.erase(it.base(), str.end());
122 inline std::string &
rtrim(std::string &str,
const std::string &filter) {
124 std::find_if(str.rbegin(), str.rend(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
125 str.erase(it.base(), str.end());
133 inline std::string &
trim(std::string &str,
const std::string filter) {
return ltrim(
rtrim(str, filter), filter); }
143 if(str.length() > 1 && (str.front() ==
'"' || str.front() ==
'\'')) {
144 if(str.front() == str.back()) {
146 str.erase(str.begin(), str.begin() + 1);
153 inline std::string
trim_copy(
const std::string &str,
const std::string &filter) {
155 return trim(s, filter);
158 inline std::ostream &
format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) {
160 out << std::setw(static_cast<int>(wid)) << std::left << name;
161 if(!description.empty()) {
162 if(name.length() >= wid)
163 out <<
"\n" << std::setw(
static_cast<int>(wid)) <<
"";
164 for(
const char c : description) {
167 out << std::setw(static_cast<int>(wid)) <<
"";
177 return std::isalnum(c, std::locale()) || c ==
'_' || c ==
'?' || c ==
'@';
187 for(
auto c : str.substr(1))
195 return std::all_of(str.begin(), str.end(), [](
char c) { return std::isalpha(c, std::locale()); });
200 std::transform(std::begin(str), std::end(str), std::begin(str), [](
const std::string::value_type &x) {
201 return std::tolower(x, std::locale());
208 str.erase(std::remove(std::begin(str), std::end(str),
'_'), std::end(str));
215 std::size_t start_pos = 0;
217 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
218 str.replace(start_pos, from.length(), to);
219 start_pos += to.length();
227 return (flags.find_first_of(
"{!") != std::string::npos);
231 auto loc = flags.find_first_of(
'{');
232 while(loc != std::string::npos) {
233 auto finish = flags.find_first_of(
"},", loc + 1);
234 if((finish != std::string::npos) && (flags[finish] ==
'}')) {
235 flags.erase(flags.begin() +
static_cast<std::ptrdiff_t
>(loc),
236 flags.begin() +
static_cast<std::ptrdiff_t
>(finish) + 1);
238 loc = flags.find_first_of(
'{', loc + 1);
240 flags.erase(std::remove(flags.begin(), flags.end(),
'!'), flags.end());
245 const std::vector<std::string> names,
248 auto it = std::end(names);
252 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
257 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
264 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
268 it = std::find(std::begin(names), std::end(names), name);
271 return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
276 template <
typename Callable>
inline std::string
find_and_modify(std::string str, std::string trigger, Callable modify) {
277 std::size_t start_pos = 0;
278 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
279 start_pos = modify(str, start_pos);
286 inline std::vector<std::string>
split_up(std::string str,
char delimiter =
'\0') {
288 const std::string delims(
"\'\"`");
289 auto find_ws = [delimiter](
char ch) {
290 return (delimiter ==
'\0') ? (std::isspace<char>(ch, std::locale()) != 0) : (ch == delimiter);
294 std::vector<std::string> output;
295 bool embeddedQuote =
false;
297 while(!str.empty()) {
298 if(delims.find_first_of(str[0]) != std::string::npos) {
300 auto end = str.find_first_of(keyChar, 1);
301 while((end != std::string::npos) && (str[end - 1] ==
'\\')) {
302 end = str.find_first_of(keyChar, end + 1);
303 embeddedQuote =
true;
305 if(end != std::string::npos) {
306 output.push_back(str.substr(1, end - 1));
307 str = str.substr(end + 1);
309 output.push_back(str.substr(1));
313 auto it = std::find_if(std::begin(str), std::end(str), find_ws);
314 if(it != std::end(str)) {
315 std::string value = std::string(str.begin(), it);
316 output.push_back(value);
317 str = std::string(it + 1, str.end());
319 output.push_back(str);
325 output.back() =
find_and_replace(output.back(), std::string(
"\\") + keyChar, std::string(1, keyChar));
326 embeddedQuote =
false;
337 inline std::string
fix_newlines(
const std::string &leader, std::string input) {
338 std::string::size_type n = 0;
339 while(n != std::string::npos && n < input.size()) {
340 n = input.find(
'\n', n);
341 if(n != std::string::npos) {
342 input = input.substr(0, n + 1) + leader + input.substr(n + 1);
354 auto next = str[offset + 1];
355 if((next ==
'\"') || (next ==
'\'') || (next ==
'`')) {
356 auto astart = str.find_last_of(
"-/ \"\'`", offset - 1);
357 if(astart != std::string::npos) {
358 if(str[astart] == ((str[offset] ==
'=') ?
'-' :
'/'))
367 if((str.front() !=
'"' && str.front() !=
'\'') || str.front() != str.back()) {
368 char quote = str.find(
'"') < str.find(
'\'') ?
'\'' :
'"';
369 if(str.find(
' ') != std::string::npos) {
370 str.insert(0, 1, quote);
371 str.append(1, quote);
std::string & remove_quotes(std::string &str)
remove quotes at the front and back of a string either '"' or '\''
Definition: StringTools.hpp:142
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.
Definition: StringTools.hpp:244
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::string remove_underscore(std::string str)
remove underscores from a string
Definition: StringTools.hpp:207
std::string find_and_modify(std::string str, std::string trigger, Callable modify)
Definition: StringTools.hpp:276
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition: StringTools.hpp:136
std::string fix_newlines(const std::string &leader, std::string input)
Definition: StringTools.hpp:337
void remove_default_flag_values(std::string &flags)
Definition: StringTools.hpp:230
bool valid_later_char(T c)
Verify following characters of an option.
Definition: StringTools.hpp:181
constexpr int expected_max_vector_size
Definition: StringTools.hpp:39
std::vector< std::string > split(const std::string &s, char delim)
Split a string by a delim.
Definition: StringTools.hpp:42
std::vector< std::string > split_up(std::string str, char delimiter='\0')
Definition: StringTools.hpp:286
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition: StringTools.hpp:59
std::string find_and_replace(std::string str, std::string from, std::string to)
Find and replace a substring with another substring.
Definition: StringTools.hpp:213
std::size_t escape_detect(std::string &str, std::size_t offset)
Definition: StringTools.hpp:353
bool isalpha(const std::string &str)
Verify that str consists of letters only.
Definition: StringTools.hpp:194
std::string & ltrim(std::string &str)
Trim whitespace from left of string.
Definition: StringTools.hpp:101
std::string & trim(std::string &str)
Trim whitespace from string.
Definition: StringTools.hpp:130
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition: StringTools.hpp:199
bool has_default_flag_values(const std::string &flags)
check if the flag definitions has possible false flags
Definition: StringTools.hpp:226
std::string & rtrim(std::string &str)
Trim whitespace from right of string.
Definition: StringTools.hpp:115
std::ostream & format_help(std::ostream &out, std::string name, std::string description, std::size_t wid)
Print a two part "help" string.
Definition: StringTools.hpp:158
std::string & add_quotes_if_needed(std::string &str)
Add quotes if the string contains spaces.
Definition: StringTools.hpp:366
std::string rjoin(const T &v, std::string delim=",")
Join a string in reverse order.
Definition: StringTools.hpp:88
std::ostream & operator<<(std::ostream &in, const T &item)
output streaming for enumerations
Definition: StringTools.hpp:26
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: Validators.hpp:902
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition: Validators.hpp:905