|
|
@@ -27,15 +27,35 @@ tokenizer &tokenizer::ignore_empty_tokens(bool new_ignore_empty_tokens) {
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
-std::vector<std::string> tokenizer::operator()(std::string const &input) const {
|
|
|
+tokenizer &tokenizer::escapable(bool new_escapable) {
|
|
|
+ escapable_ = new_escapable;
|
|
|
+ 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::size_t tokenizer::find(std::string &input, std::size_t from) const {
|
|
|
+ auto pos = input.find(divider_, from);
|
|
|
+ while (escapable_ && pos != std::string::npos &&
|
|
|
+ countback(input, pos, '\\') % 2) {
|
|
|
+ input.erase(pos - 1, 1);
|
|
|
+ pos = input.find(divider_, pos);
|
|
|
+ }
|
|
|
+ return pos;
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<std::string> tokenizer::operator()(std::string input) const {
|
|
|
std::vector<std::string> rval;
|
|
|
// If max_outputs_ == infinite_outputs, this will be infinite enough to work
|
|
|
// since we'll hit overflow on the string itself before this.
|
|
|
size_t const max = max_outputs_ - !truncate_;
|
|
|
size_t i = 0;
|
|
|
- for (size_t n = input.find(divider_);
|
|
|
+ for (size_t n = find(input, i);
|
|
|
n != std::string::npos && rval.size() < max;
|
|
|
- i = n + 1, n = input.find(divider_, i)) {
|
|
|
+ i = n + 1, n = find(input, i)) {
|
|
|
if (ignore_empty_tokens_ && i == n) {
|
|
|
continue;
|
|
|
}
|