|
|
@@ -10,6 +10,10 @@
|
|
|
|
|
|
namespace string_utils {
|
|
|
|
|
|
+template <typename C> static void reverse(C & str) {
|
|
|
+ std::reverse(str.begin(), str.end());
|
|
|
+}
|
|
|
+
|
|
|
tokenizer::tokenizer(std::string divider, struct quote quote)
|
|
|
: divider_(std::move(divider)), quote_(std::move(quote)) {}
|
|
|
|
|
|
@@ -33,17 +37,28 @@ tokenizer & tokenizer::escapable(bool new_escapable) {
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
+tokenizer & tokenizer::reverse_search(bool new_reverse) {
|
|
|
+ if (reverse_search_ != new_reverse) {
|
|
|
+ reverse(divider_);
|
|
|
+ reverse(quote_.escaped);
|
|
|
+ }
|
|
|
+ reverse_search_ = new_reverse;
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
static std::size_t countback(std::string const & str, std::size_t p, char c) {
|
|
|
if (p == 0 || str[p - 1] != c) return 0;
|
|
|
return p - str.find_last_not_of(c, p - 1) - 1;
|
|
|
}
|
|
|
|
|
|
-std::vector<std::string>
|
|
|
-tokenizer::operator()(std::string const & input) const {
|
|
|
+std::vector<std::string> tokenizer::operator()(std::string input) const {
|
|
|
auto equals_from = [&input](std::string const & token, std::size_t from) {
|
|
|
return token.size() + from < input.size() &&
|
|
|
std::strncmp(input.c_str() + from, token.c_str(), token.size()) == 0;
|
|
|
};
|
|
|
+
|
|
|
+ if (reverse_search_) { reverse(input); }
|
|
|
+
|
|
|
std::vector<std::string> rval;
|
|
|
std::string buffer;
|
|
|
buffer.reserve(input.size());
|
|
|
@@ -82,6 +97,13 @@ tokenizer::operator()(std::string const & input) const {
|
|
|
if (rval.size() < max_outputs_ && !(buffer.empty() && from == input.size())) {
|
|
|
rval.emplace_back(buffer.empty() ? input.substr(from) : buffer);
|
|
|
}
|
|
|
+
|
|
|
+ if (reverse_search_) {
|
|
|
+ reverse(rval);
|
|
|
+ for (auto & str : rval) {
|
|
|
+ reverse(str);
|
|
|
+ }
|
|
|
+ }
|
|
|
return rval;
|
|
|
}
|
|
|
|