12 #include <type_traits> 22 template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
23 std::ostream &
operator<<(std::ostream &in,
const T &item) {
25 return in << static_cast<typename std::underlying_type<T>::type>(item);
29 template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
31 typename std::underlying_type<T>::type i;
33 item =
static_cast<T
>(i);
39 using namespace enums;
45 inline std::vector<std::string> split(
const std::string &s,
char delim) {
46 std::vector<std::string> elems;
54 while(std::getline(ss, item, delim)) {
55 elems.push_back(item);
61 template <
typename T>
inline std::string as_string(
const T &v) {
67 template <typename T, typename = typename std::enable_if<std::is_constructible<std::string, T>::value>::type>
68 inline auto as_string(T &&v) -> decltype(std::forward<T>(v)) {
69 return std::forward<T>(v);
73 template <
typename T> std::string join(
const T &v, std::string delim =
",") {
75 auto beg = std::begin(v);
76 auto end = std::end(v);
88 typename =
typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
89 std::string join(
const T &v, Callable func, std::string delim =
",") {
91 auto beg = std::begin(v);
92 auto end = std::end(v);
96 s << delim << func(*beg++);
102 template <
typename T> std::string rjoin(
const T &v, std::string delim =
",") {
103 std::ostringstream s;
104 for(
size_t start = 0; start < v.size(); start++) {
107 s << v[v.size() - start - 1];
115 inline std::string <rim(std::string &str) {
116 auto it = std::find_if(str.begin(), str.end(), [](
char ch) {
return !std::isspace<char>(ch, std::locale()); });
117 str.erase(str.begin(), it);
122 inline std::string <rim(std::string &str,
const std::string &filter) {
123 auto it = std::find_if(str.begin(), str.end(), [&filter](
char ch) {
return filter.find(ch) == std::string::npos; });
124 str.erase(str.begin(), it);
129 inline std::string &rtrim(std::string &str) {
130 auto it = std::find_if(str.rbegin(), str.rend(), [](
char ch) {
return !std::isspace<char>(ch, std::locale()); });
131 str.erase(it.base(), str.end());
136 inline std::string &rtrim(std::string &str,
const std::string &filter) {
138 std::find_if(str.rbegin(), str.rend(), [&filter](
char ch) {
return filter.find(ch) == std::string::npos; });
139 str.erase(it.base(), str.end());
144 inline std::string &trim(std::string &str) {
return ltrim(rtrim(str)); }
147 inline std::string &trim(std::string &str,
const std::string filter) {
return ltrim(rtrim(str, filter), filter); }
150 inline std::string trim_copy(
const std::string &str) {
156 inline std::string trim_copy(
const std::string &str,
const std::string &filter) {
158 return trim(s, filter);
161 inline std::ostream &format_help(std::ostream &out, std::string name, std::string description,
size_t wid) {
163 out << std::setw(static_cast<int>(wid)) << std::left << name;
164 if(!description.empty()) {
165 if(name.length() >= wid)
166 out <<
"\n" << std::setw(static_cast<int>(wid)) <<
"";
167 for(
const char c : description) {
170 out << std::setw(static_cast<int>(wid)) <<
"";
179 template <
typename T>
bool valid_first_char(T c) {
180 return std::isalnum(c, std::locale()) || c ==
'_' || c ==
'?' || c ==
'@';
184 template <
typename T>
bool valid_later_char(T c) {
return valid_first_char(c) || c ==
'.' || c ==
'-'; }
187 inline bool valid_name_string(
const std::string &str) {
188 if(str.empty() || !valid_first_char(str[0]))
190 for(
auto c : str.substr(1))
191 if(!valid_later_char(c))
197 inline bool isalpha(
const std::string &str) {
198 return std::all_of(str.begin(), str.end(), [](
char c) {
return std::isalpha(c, std::locale()); });
202 inline std::string to_lower(std::string str) {
203 std::transform(std::begin(str), std::end(str), std::begin(str), [](
const std::string::value_type &x) {
204 return std::tolower(x, std::locale());
210 inline std::string remove_underscore(std::string str) {
211 str.erase(std::remove(std::begin(str), std::end(str),
'_'), std::end(str));
216 inline std::string find_and_replace(std::string str, std::string from, std::string to) {
218 size_t start_pos = 0;
220 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
221 str.replace(start_pos, from.length(), to);
222 start_pos += to.length();
229 inline bool has_default_flag_values(
const std::string &flags) {
230 return (flags.find_first_of(
"{!") != std::string::npos);
233 inline void remove_default_flag_values(std::string &flags) {
234 auto loc = flags.find_first_of(
'{');
235 while(loc != std::string::npos) {
236 auto finish = flags.find_first_of(
"},", loc + 1);
237 if((finish != std::string::npos) && (flags[finish] ==
'}')) {
238 flags.erase(flags.begin() +
static_cast<std::ptrdiff_t
>(loc),
239 flags.begin() +
static_cast<std::ptrdiff_t
>(finish) + 1);
241 loc = flags.find_first_of(
'{', loc + 1);
243 flags.erase(std::remove(flags.begin(), flags.end(),
'!'), flags.end());
247 inline std::ptrdiff_t find_member(std::string name,
248 const std::vector<std::string> names,
249 bool ignore_case =
false,
250 bool ignore_underscore =
false) {
251 auto it = std::end(names);
253 if(ignore_underscore) {
254 name = detail::to_lower(detail::remove_underscore(name));
255 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
256 return detail::to_lower(detail::remove_underscore(local_name)) == name;
259 name = detail::to_lower(name);
260 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
261 return detail::to_lower(local_name) == name;
265 }
else if(ignore_underscore) {
266 name = detail::remove_underscore(name);
267 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
268 return detail::remove_underscore(local_name) == name;
271 it = std::find(std::begin(names), std::end(names), name);
273 return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
278 template <
typename Callable>
inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
279 size_t start_pos = 0;
280 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
281 start_pos = modify(str, start_pos);
288 inline std::vector<std::string> split_up(std::string str) {
290 const std::string delims(
"\'\"`");
291 auto find_ws = [](
char ch) {
return std::isspace<char>(ch, std::locale()); };
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, 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(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);
353 inline size_t escape_detect(std::string &str,
size_t offset) {
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] ==
'=') ?
'-' :
'/'))
366 inline std::string &add_quotes_if_needed(std::string &str) {
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::istream & operator>>(std::istream &in, T &item)
input streaming for enumerations
Definition: StringTools.hpp:30
std::ostream & operator<<(std::ostream &in, const T &item)
output streaming for enumerations
Definition: StringTools.hpp:23