// A lot of this is taken from async/rxx.C in sfslite, but with some // modifications for returning the matched pattern. // int split2 (vec<str> *out, rxx pat, str expr, size_t lim, bool emptylast) { const char *p = expr; const char *const e = p + expr.len (); size_t n; if (out) out->clear (); // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). for (n = 0; p < e && n + 1 < lim; n++) { if (!pat._exec (p, e - p, 0)) { return 0; } if (!pat.success ()) break; if (out) { out->push_back (str (p, pat.start (0))); str sep (p + pat.start (0), pat.len (0)); out->push_back (sep); } p += max (pat.end (0), 1); } if (lim && (p < e || emptylast)) { n++; if (out) { out->push_back (str (p, e - p)); } } return n; }
void repl_el_capture_t::output (strbuf &out, const char *s, rxx &x) { int start = x.start (_i); int ln = x.len (_i); if (start >= 0 && ln > 0) { str repl = str (s + start, ln); strbuf_output (out, repl); } }
static void extract_matches (vec<str> *out, const char *base, rxx &x) { bool go = true; for (int i = 0; go; i++) { int ln = x.len (i); int start = x.start (i); if (ln < 0 || start < 0) { go = false; } else if (ln > 0) { out->push_back (str (base + start, ln)); } } }
str rxx_replace_2 (str input, rxx pat, str repl_str) { repl_t repl; str ret; if (!repl.parse (repl_str)) { warn << "XX cannot parse replacement string: " << repl_str << "\n"; } else { const char *p = input; const char *const e = p + input.len (); strbuf b; bool go = true; bool err = false; // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). while (go && !err && p < e) { if (!pat._exec (p, e - p, 0)) { warn << "XX regex execution failed\n"; err = true; } else if (!pat.success ()) { go = false; } else { str pre = str (p, pat.start (0)); strbuf_output (b, pre); repl.output (b, p, pat); p += max (pat.end (0), 1); } } if (p < e && !err) { str post = str (p, e - p); strbuf_output (b, post); } if (!err) { ret = b; } } return ret; }
// Call the replace function for each matched pattern. str rxx_replace (str input, rxx pat, rxx_replace_cb_t cb) { const char *p = input; const char *const e = p + input.len (); strbuf b; bool go = true; bool err = false; str ret; // check p < e to see that we're not dealing with an empty // string (especially since x? matches ""). while (go && !err && p < e) { if (!pat._exec (p, e - p, 0)) { warn << "XX regex execution failed\n"; err = true; } else if (!pat.success ()) { go = false; } else { str pre = str (p, pat.start (0)); strbuf_output (b, pre); vec<str> v; extract_matches (&v, p, pat); str repl = (*cb) (&v); if (repl) { strbuf_output (b, repl); } p += max (pat.end (0), 1); } } if (p < e && !err) { str post = str (p, e - p); strbuf_output (b, post); } if (!err) { ret = b; } return ret; }