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);
31 using enums::operator<<;
39 inline std::vector<std::string>
split(
const std::string &s,
char delim) {
40 std::vector<std::string> elems;
48 while(std::getline(ss, item, delim)) {
49 elems.push_back(item);
56 template <
typename T> std::string
join(
const T &v, std::string delim =
",") {
58 auto beg = std::begin(v);
59 auto end = std::end(v);
71 typename =
typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
72 std::string
join(
const T &v, Callable func, std::string delim =
",") {
74 auto beg = std::begin(v);
75 auto end = std::end(v);
79 s << delim << func(*beg++);
85 template <
typename T> std::string
rjoin(
const T &v, std::string delim =
",") {
87 for(std::size_t start = 0; start < v.size(); start++) {
90 s << v[v.size() - start - 1];
98 inline std::string &
ltrim(std::string &str) {
99 auto it = std::find_if(str.begin(), str.end(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
100 str.erase(str.begin(), it);
105 inline std::string &
ltrim(std::string &str,
const std::string &filter) {
106 auto it = std::find_if(str.begin(), str.end(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
107 str.erase(str.begin(), it);
112 inline std::string &
rtrim(std::string &str) {
113 auto it = std::find_if(str.rbegin(), str.rend(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
114 str.erase(it.base(), str.end());
119 inline std::string &
rtrim(std::string &str,
const std::string &filter) {
121 std::find_if(str.rbegin(), str.rend(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
122 str.erase(it.base(), str.end());
130 inline std::string &
trim(std::string &str,
const std::string filter) {
return ltrim(
rtrim(str, filter), filter); }
140 if(str.length() > 1 && (str.front() ==
'"' || str.front() ==
'\'')) {
141 if(str.front() == str.back()) {
143 str.erase(str.begin(), str.begin() + 1);
150 inline std::string
trim_copy(
const std::string &str,
const std::string &filter) {
152 return trim(s, filter);
155 inline std::ostream &
format_help(std::ostream &out, std::string name, std::string description, std::size_t wid) {
157 out << std::setw(static_cast<int>(wid)) << std::left << name;
158 if(!description.empty()) {
159 if(name.length() >= wid)
160 out <<
"\n" << std::setw(
static_cast<int>(wid)) <<
"";
161 for(
const char c : description) {
164 out << std::setw(static_cast<int>(wid)) <<
"";
174 return std::isalnum(c, std::locale()) || c ==
'_' || c ==
'?' || c ==
'@';
184 for(
auto c : str.substr(1))
192 return std::all_of(str.begin(), str.end(), [](
char c) { return std::isalpha(c, std::locale()); });
197 std::transform(std::begin(str), std::end(str), std::begin(str), [](
const std::string::value_type &x) {
198 return std::tolower(x, std::locale());
205 str.erase(std::remove(std::begin(str), std::end(str),
'_'), std::end(str));
212 std::size_t start_pos = 0;
214 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
215 str.replace(start_pos, from.length(), to);
216 start_pos += to.length();
224 return (flags.find_first_of(
"{!") != std::string::npos);
228 auto loc = flags.find_first_of(
'{');
229 while(loc != std::string::npos) {
230 auto finish = flags.find_first_of(
"},", loc + 1);
231 if((finish != std::string::npos) && (flags[finish] ==
'}')) {
232 flags.erase(flags.begin() +
static_cast<std::ptrdiff_t
>(loc),
233 flags.begin() +
static_cast<std::ptrdiff_t
>(finish) + 1);
235 loc = flags.find_first_of(
'{', loc + 1);
237 flags.erase(std::remove(flags.begin(), flags.end(),
'!'), flags.end());
242 const std::vector<std::string> names,
245 auto it = std::end(names);
249 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
254 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
261 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
265 it = std::find(std::begin(names), std::end(names), name);
267 return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
272 template <
typename Callable>
inline std::string
find_and_modify(std::string str, std::string trigger, Callable modify) {
273 std::size_t start_pos = 0;
274 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
275 start_pos = modify(str, start_pos);
282 inline std::vector<std::string>
split_up(std::string str,
char delimiter =
'\0') {
284 const std::string delims(
"\'\"`");
285 auto find_ws = [delimiter](
char ch) {
286 return (delimiter ==
'\0') ? (std::isspace<char>(ch, std::locale()) != 0) : (ch == delimiter);
290 std::vector<std::string> output;
291 bool embeddedQuote =
false;
293 while(!str.empty()) {
294 if(delims.find_first_of(str[0]) != std::string::npos) {
296 auto end = str.find_first_of(keyChar, 1);
297 while((end != std::string::npos) && (str[end - 1] ==
'\\')) {
298 end = str.find_first_of(keyChar, end + 1);
299 embeddedQuote =
true;
301 if(end != std::string::npos) {
302 output.push_back(str.substr(1, end - 1));
303 str = str.substr(end + 1);
305 output.push_back(str.substr(1));
309 auto it = std::find_if(std::begin(str), std::end(str), find_ws);
310 if(it != std::end(str)) {
311 std::string value = std::string(str.begin(), it);
312 output.push_back(value);
313 str = std::string(it + 1, str.end());
315 output.push_back(str);
321 output.back() =
find_and_replace(output.back(), std::string(
"\\") + keyChar, std::string(1, keyChar));
322 embeddedQuote =
false;
333 inline std::string
fix_newlines(
const std::string &leader, std::string input) {
334 std::string::size_type n = 0;
335 while(n != std::string::npos && n < input.size()) {
336 n = input.find(
'\n', n);
337 if(n != std::string::npos) {
338 input = input.substr(0, n + 1) + leader + input.substr(n + 1);
350 auto next = str[offset + 1];
351 if((next ==
'\"') || (next ==
'\'') || (next ==
'`')) {
352 auto astart = str.find_last_of(
"-/ \"\'`", offset - 1);
353 if(astart != std::string::npos) {
354 if(str[astart] == ((str[offset] ==
'=') ?
'-' :
'/'))
363 if((str.front() !=
'"' && str.front() !=
'\'') || str.front() != str.back()) {
364 char quote = str.find(
'"') < str.find(
'\'') ?
'\'' :
'"';
365 if(str.find(
' ') != std::string::npos) {
366 str.insert(0, 1, quote);
367 str.append(1, quote);