It can't blow up
Every match is O(n·m) — no backtracking, so no catastrophic path: ReDoS-safe by construction.
A linear-time, ReDoS-safe regex engine for C++20 — drop-in for std::regex, RE2, Python re, and the Rust regex crate, plus a regexp-shaped Go binding. Every divergence documented per surface. Match untrusted input without ever falling off a backtracking cliff.
Every match is O(n·m) — no backtracking, so no catastrophic path: ReDoS-safe by construction.
Drop-ins for std::regex, RE2, Python re, the Rust regex crate, a regexp-shaped Go API, and a frozen C ABI — one linear engine underneath, each surface's divergences documented.
Hold a real::static_regex as a constexpr object; the pattern lives in the type, a few dozen headers, nothing to link. real::regex allocates — it is not a constexpr variable.
The pattern below is harmless-looking and perfectly valid. On a long run of as ending in the wrong byte, a backtracking engine explores an exponential number of paths. real walks it once.
Same regex, same string. The only difference is whether the engine can be forced off a cliff by input it didn't choose — the difference between a feature and a denial-of-service.
If you know std::regex, re or the regex crate, you already know this API. The Go binding is regexp-shaped (MatchString, Find, Split).
// The pattern lives in the type — parsed & compiled at compile time. #include <real/real.hpp> constexpr real::static_regex<R"((\w+)@(\w+))"> email; static_assert(email.search("info@example.com")[2] == "example");
import real as re # drop-in for the standard library's re m = re.search(r"(\w+)@(\w+)", "info@example.com") m.group(2) # 'example' — linear time, no backtracking cliff
use real_regex::Regex; // drop-in for the regex crate let re = Regex::new(r"(\w+)@(\w+)")?; let caps = re.captures("info@example.com").unwrap(); &caps[2]; // "example"
import real "github.com/RECHE23/real-regex/bindings/go" re := real.MustCompile(`\d+`) fmt.Print(re.MatchString("x42"))
// every snippet verified against the current public API
The std::regex and RE2 layers document every intentional divergence, down to per-standard-library behavior. No silent surprises: the contract says exactly what the engine does, and CI enforces it.
A pattern becomes an NFA program, matched by a Pike VM with a lazy-DFA fast path and a SIMD prefilter — the classic linear-time pipeline, in modern constexpr C++.