159 lines
4.9 KiB
C++
159 lines
4.9 KiB
C++
|
|
#include "ml_string.h"
|
|
|
|
|
|
// Replace a substring with a replacement string in a source string
|
|
void replace_substring(std::string &src, const std::string &substr, const std::string &replacement) {
|
|
size_t i = 0;
|
|
for (i = src.find(substr, i); i != std::string::npos; i = src.find(substr, i)) {
|
|
src.replace(i, substr.size(), replacement);
|
|
i += replacement.size();
|
|
}
|
|
}
|
|
|
|
// Return string where substring regex is replaced with a replacement regex
|
|
std::string replace_substring_regexp(const std::string &src, const std::string &substr, const std::string &replacement) {
|
|
std::regex e{substr};
|
|
return std::regex_replace(src, e, replacement);
|
|
}
|
|
|
|
|
|
// Returns true if where contains regex
|
|
bool regexp_search(const std::string &where, const std::string ®ex_str) {
|
|
// online tester https://www.regextester.com/97722
|
|
std::regex regex(regex_str);
|
|
std::smatch match;
|
|
|
|
if (std::regex_search(where, match, regex)) {
|
|
// std::cout << "matches for '" << where << "'\n";
|
|
// std::cout << "Prefix: '" << match.prefix() << "'\n";
|
|
// for (size_t i = 0; i < match.size(); ++i)
|
|
// std::cout << i << ": " << match[i] << '\n';
|
|
// std::cout << "Suffix: '" << match.suffix() << "\'\n\n";
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> regexp_strsplit(const std::string &string_to_split, const std::string &rgx_str) {
|
|
std::vector<std::string> elems;
|
|
|
|
std::regex rgx(rgx_str);
|
|
std::sregex_token_iterator iter(string_to_split.begin(), string_to_split.end(), rgx, -1);
|
|
std::sregex_token_iterator end;
|
|
|
|
for (; iter != end; ++iter)
|
|
elems.push_back(*iter);
|
|
|
|
return elems;
|
|
}
|
|
|
|
|
|
std::vector<std::string> regexp_match(const std::string &str, const std::string ®_ex, bool case_sensitive) {
|
|
std::vector<std::string> matches;
|
|
|
|
std::regex pars_regex(reg_ex); // , (case_sensitive ? std::regex::basic : std::regex::basic|std::regex::icase));
|
|
auto words_begin = std::sregex_iterator(str.begin(), str.end(), pars_regex);
|
|
auto words_end = std::sregex_iterator();
|
|
|
|
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
|
|
std::smatch match = *i;
|
|
matches.push_back(match.str());
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
std::vector<std::vector<std::string>> regexp_tokens(const std::string &str, const std::string ®_ex, bool case_sensitive) {
|
|
std::vector<std::vector<std::string>> captured_groups;
|
|
std::vector<std::string> captured_subgroups;
|
|
|
|
std::smatch res;
|
|
std::regex exp(reg_ex); // , (case_sensitive ? std::regex::basic : std::regex::basic|std::regex::icase));
|
|
std::string::const_iterator searchStart(str.cbegin());
|
|
while (std::regex_search(searchStart, str.cend(), res, exp)) {
|
|
captured_subgroups.clear();
|
|
if (res.size() == 1) { // no subgroups
|
|
captured_subgroups.push_back(res[0]);
|
|
} else {
|
|
for (size_t i = 1; i < res.size(); ++i) { // [0] is whole match
|
|
captured_subgroups.push_back(res[i]);
|
|
}
|
|
}
|
|
if (!captured_subgroups.empty())
|
|
captured_groups.push_back(captured_subgroups);
|
|
|
|
searchStart += res.position() + res.length();
|
|
}
|
|
return captured_groups;
|
|
}
|
|
|
|
std::vector<std::vector<std::string>> regexp_search2(const std::string &string_to_split, const std::string &rgx_str, bool match_mode, bool ignore_case) {
|
|
if (match_mode) {
|
|
std::vector<std::vector<std::string>> matches{regexp_match(string_to_split, rgx_str, ignore_case)};
|
|
return matches;
|
|
} else {
|
|
return regexp_tokens(string_to_split, rgx_str, ignore_case);
|
|
}
|
|
}
|
|
|
|
std::string string_lucase(std::string s, const std::string &strcase) {
|
|
if (strcase == "upper")
|
|
std::transform(s.begin(), s.end(),s.begin(), ::toupper);
|
|
|
|
if (strcase == "lower")
|
|
std::transform(s.begin(), s.end(),s.begin(), ::tolower);
|
|
|
|
return s;
|
|
}
|
|
|
|
std::string string_trim(std::string s, const std::string &chars_to_trim, const std::string &rltrim) {
|
|
if (rltrim == "ltrim" || rltrim == "trim")
|
|
s.erase(0, s.find_first_not_of(chars_to_trim));
|
|
|
|
if (rltrim == "rtrim" || rltrim == "trim")
|
|
s.erase(s.find_last_not_of(chars_to_trim)+1);
|
|
|
|
return s;
|
|
}
|
|
|
|
std::string string_padd(const std::string &str, size_t pad_len, char fill_char, bool from_right) {
|
|
auto str_len = str.length();
|
|
|
|
if (str_len == pad_len)
|
|
return str;
|
|
else if (str_len > pad_len) {
|
|
return (from_right ? str.substr(0, pad_len) : str.substr(str_len - pad_len, std::string::npos));
|
|
}
|
|
|
|
if (from_right)
|
|
return str + std::string(pad_len - str.size(), fill_char);
|
|
else
|
|
return std::string(pad_len - str.size(), fill_char) + str;
|
|
}
|
|
|
|
|
|
std::string string_substring(const std::string & str, long pos, size_t count) {
|
|
size_t start_pos = pos;
|
|
|
|
if (pos < 0) {
|
|
start_pos = str.size() - abs(pos);
|
|
}
|
|
|
|
if ( (start_pos >= str.size()) || (count < 1) || (start_pos < 0) ) {
|
|
throw std::invalid_argument("Invalid parameter(s) for string-substr.");
|
|
}
|
|
|
|
return str.substr(start_pos, count);
|
|
}
|
|
|
|
long string_find_substr(const std::string & str, const std::string & pattern, size_t pos) {
|
|
if (pos >= str.size()) {
|
|
throw std::invalid_argument("Invalid parameter(s) for string-find.");
|
|
}
|
|
|
|
size_t p = str.find(pattern, pos);
|
|
|
|
return p != std::string::npos ? p : -1;
|
|
}
|