|
REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
|
A compiled regular expression, parameterized on its storage policy. More...
#include <real.hpp>
Public Types | |
| using | result_type = basic_match_result< typename Storage::slot_storage > |
| This regex's match-result type. | |
| using | owning_result_type = basic_match_result< typename Storage::slot_storage, typename Storage::name_owner > |
| What a single attempt on a temporary regex yields. | |
Public Member Functions | |
| constexpr | basic_regex (std::string_view pattern, flags compile_flags=flags::none) |
Compiles pattern at run time (the real::regex constructor). | |
| constexpr | basic_regex ()=default |
| Default constructor for the stateless compile-time storage (static_regex). | |
| constexpr result_type | match (std::string_view text) const & |
Match anchored at the start of text (Python re.match). | |
| constexpr result_type | fullmatch (std::string_view text) const & |
Match the entire text (Python re.fullmatch). | |
| constexpr result_type | search (std::string_view text) const & |
Leftmost match anywhere in text (Python re.search). | |
| constexpr result_type | match (std::string_view text, std::size_t pos, std::size_t endpos=npos) const & |
Region-aware match: anchored at pos within text[0:endpos] (Python re.match with pos / endpos). Byte offsets; pos is not a slice (see run — \A fails at pos > 0); endpos defaults to the end of text. | |
| constexpr result_type | fullmatch (std::string_view text, std::size_t pos, std::size_t endpos=npos) const & |
Region-aware fullmatch: the whole region [pos, endpos) must match. | |
| constexpr result_type | search (std::string_view text, std::size_t pos, std::size_t endpos=npos) const & |
Region-aware search: leftmost match within [pos, endpos). | |
| constexpr result_type | match (const char *text) const & |
match overload for string literals. | |
| constexpr result_type | fullmatch (const char *text) const & |
fullmatch overload for string literals. | |
| constexpr result_type | search (const char *text) const & |
search overload for string literals. | |
| constexpr owning_result_type | match (std::string_view text) const && |
match on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | fullmatch (std::string_view text) const && |
fullmatch on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | search (std::string_view text) const && |
search on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | match (std::string_view text, std::size_t pos, std::size_t endpos=npos) const && |
Region-aware match on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | fullmatch (std::string_view text, std::size_t pos, std::size_t endpos=npos) const && |
Region-aware fullmatch on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | search (std::string_view text, std::size_t pos, std::size_t endpos=npos) const && |
Region-aware search on a temporary regex; the result owns its name context. | |
| constexpr owning_result_type | match (const char *text) const && |
match on a temporary regex, string-literal overload. | |
| constexpr owning_result_type | fullmatch (const char *text) const && |
fullmatch on a temporary regex, string-literal overload. | |
| constexpr owning_result_type | search (const char *text) const && |
search on a temporary regex, string-literal overload. | |
| constexpr basic_match_range< Storage > | find_iter (std::string_view text) const & |
Lazy range over all non-overlapping matches (Python re.finditer). | |
| constexpr basic_match_range< Storage > | find_iter (const char *text) const & |
find_iter overload for string literals. | |
| constexpr basic_match_range< Storage > | find_iter (std::string_view text, std::size_t pos, std::size_t endpos=npos) const & |
Region-aware find_iter: iterate matches within [pos, endpos) (Python finditer with pos / endpos). endpos truncates the subject to a view so iteration stops at it; pos is the start, not a slice (see run). Byte offsets; endpos defaults to the end of text. | |
| constexpr basic_match_range< Storage > | find_iter_longest (std::string_view text, std::size_t pos=0, std::size_t endpos=npos) const & |
Experimental leftmost-**longest** find_iter: iterate matches with POSIX (leftmost-longest) bounds rather than the default leftmost-first — the iterator twin of search_longest, sharing its prototype status. Region semantics match find_iter — endpos truncates the subject to a view, pos is the start (not a slice). Byte offsets; captures are the winning thread's, not POSIX submatch. Every fast path is bypassed. | |
| basic_match_range< Storage > | find_iter_longest (std::string_view, std::size_t, std::size_t) const &&=delete |
Deleted: find_iter_longest on a temporary regex would dangle. | |
| basic_match_range< Storage > | find_iter (std::string_view text) const &&=delete |
Deleted: find_iter on a temporary regex would dangle. | |
| basic_match_range< Storage > | find_iter (const char *text) const &&=delete |
Deleted: find_iter on a temporary regex would dangle. | |
| basic_match_range< Storage > | find_iter (std::string_view text, std::size_t, std::size_t=npos) const &&=delete |
Deleted: region find_iter on a temporary regex would dangle. | |
| constexpr std::size_t | count_matches (std::string_view text, std::size_t pos=0, std::size_t endpos=npos) const |
| Count non-overlapping matches without allocating result objects. | |
| constexpr std::vector< result_type > | find_all (std::string_view text) const & |
All matches, eagerly (like Python re.findall, but full results). | |
| constexpr std::vector< result_type > | find_all (const char *text) const & |
find_all overload for string literals. | |
| std::vector< result_type > | find_all (std::string_view text) const &&=delete |
Deleted: find_all on a temporary regex would dangle. | |
| std::vector< result_type > | find_all (const char *text) const &&=delete |
Deleted: find_all on a temporary regex would dangle. | |
| constexpr std::string | replace (std::string_view text, std::string_view replacement, std::size_t max_count=0) const |
Replaces matches in text (ECMAScript / std::regex_replace $1). | |
| constexpr std::vector< std::string_view > | split (std::string_view text, std::size_t max_splits=0) const |
Splits text on matches (Python re.split). | |
| constexpr std::vector< std::string_view > | split (const char *text, std::size_t max_splits=0) const |
split overload for string literals. | |
| result_type | match (const std::string &&text) const =delete |
| Deleted: temporary text would dangle. | |
| result_type | fullmatch (const std::string &&text) const =delete |
| Deleted: temporary text would dangle. | |
| result_type | search (const std::string &&text) const =delete |
| Deleted: temporary text would dangle. | |
| result_type | match (const std::string &&text, std::size_t, std::size_t=npos) const =delete |
| Deleted: temporary text would dangle. | |
| result_type | fullmatch (const std::string &&text, std::size_t, std::size_t=npos) const =delete |
| Deleted: temporary text would dangle. | |
| result_type | search (const std::string &&text, std::size_t, std::size_t=npos) const =delete |
| Deleted: temporary text would dangle. | |
| basic_match_range< Storage > | find_iter (const std::string &&text) const &=delete |
| Deleted: temporary text would dangle. | |
| basic_match_range< Storage > | find_iter (const std::string &&text, std::size_t, std::size_t=npos) const &=delete |
| Deleted: temporary text would dangle. | |
| std::vector< result_type > | find_all (const std::string &&text) const &=delete |
| Deleted: temporary text would dangle. | |
| std::vector< std::string_view > | split (const std::string &&text, std::size_t max_splits=0) const =delete |
| Deleted: temporary text would dangle. | |
| constexpr std::string_view | pattern () const |
| Returns the pattern text this regex was compiled from. | |
| constexpr flags | compile_flags () const |
The flag set in force: constructor flags, plus a leading (?imsxa) group, minus its -removal. | |
| constexpr std::size_t | group_count () const |
| Returns the number of capturing groups (excluding group 0). | |
| constexpr detail::program_view | raw_program () const |
| The raw compiled program, for embedders (advanced). | |
| constexpr bool | has_first_byte_set () const noexcept |
| Whether first-byte filtering is useful for this pattern. | |
| constexpr std::optional< unsigned char > | unique_first_byte () const noexcept |
| The single byte every non-empty match must begin with, if unique. | |
| constexpr bool | may_start_with (unsigned char byte) const noexcept |
Whether a non-empty match can begin with byte (sound, conservative). | |
| constexpr std::size_t | group_index (std::string_view name) const |
| Resolves a group name to its number. | |
| constexpr std::vector< std::pair< std::string_view, std::size_t > > | named_groups () const |
| All named groups as (name, number) pairs, in declaration order. | |
| constexpr std::size_t | named_group_count () const |
| How many named groups the pattern declares. | |
| constexpr std::pair< std::string_view, std::size_t > | named_group_at (std::size_t index) const |
The index-th named group, in declaration order. | |
| result_type | search_longest (std::string_view text) const |
EXPERIMENTAL, opt-in: a single leftmost-**longest** search (POSIX / RE2 set_longest_match), the default leftmost-first semantics left untouched. Among matches at the leftmost start it returns the longest; a lazy quantifier therefore behaves greedily, and captures are the leftmost-first thread's at that longest bound (not POSIX submatch). Runs on the general Pike loop (the first-match DFA / inner-literal fast paths are bypassed). A prototype for the match_semantics arc — not yet a stable API. Its iteration twin is find_iter_longest. | |
| result_type | search_longest (std::string_view text, std::size_t pos, std::size_t endpos=npos) const |
Region-aware form of search_longest — leftmost-longest search within [pos, endpos). pos is the start (not a slice, per run); endpos truncates the subject. Byte offsets. | |
Private Member Functions | |
| constexpr std::size_t | count_walk (std::string_view text, std::size_t pos, std::size_t endpos) const |
| count_matches's walk: the ordinary one, run MATCHING-ONLY. | |
| constexpr std::size_t | count_trailing_la (std::string_view region, std::size_t pos) const |
| count_matches over the trailing-lookaround walk, outlined. | |
| constexpr std::string_view | name_of (const detail::named_group &named_group) const |
| Returns its name, sliced from the pattern text. | |
| constexpr void | expand_replacement (std::string &out, const result_type &match, std::string_view replacement) const |
Appends replacement to out, substituting group references. | |
| constexpr result_type | run (std::string_view text, detail::run_mode mode) const |
| Runs a single match attempt from offset 0 (backs match/search/fullmatch). | |
| constexpr result_type | run (std::string_view text, std::size_t pos, std::size_t endpos, detail::run_mode mode, match_semantics sem=match_semantics::first) const |
Region-aware single attempt: match over text[0:endpos] starting at pos. | |
Static Private Member Functions | |
| static constexpr owning_result_type | detach (result_type result) |
| Hands a result the name context it will need after this regex is gone. | |
Private Attributes | |
| Storage | program_ |
| The storage policy holding the compiled program. | |
A compiled regular expression, parameterized on its storage policy.
Storage owns the program; matching allocates only per-run scratch — and nothing at all when the storage is compile-time. Use the real::regex and real::static_regex aliases rather than this template directly.
| Storage | real::detail::dynamic_storage or real::detail::static_storage. |
| using real::basic_regex< Storage >::owning_result_type = basic_match_result<typename Storage::slot_storage, typename Storage::name_owner> |
What a single attempt on a temporary regex yields.
Same spans and groups as result_type, plus ownership of the name tables the regex would otherwise lend. Bind it with auto. Spelling result_type (or real::match_result) does not compile, which is the point: there is no conversion that could drop the ownership and leave dangling views.
On static_regex the two aliases are the same type: the tables have static storage duration, so a result from a temporary is already safe.
|
inlineexplicitconstexpr |
Compiles pattern at run time (the real::regex constructor).
| [in] | pattern | The pattern text. |
| [in] | compile_flags | Optional flags (merged with a leading global-flags group, (?imsxaU) or (?flags-flags)). |
| real::regex_error | on an invalid or over-limit pattern. |
|
inlineconstexpr |
The flag set in force: constructor flags, plus a leading (?imsxa) group, minus its -removal.
regex("(?-i)a", flags::icase) reports no flags::icase and matches case-sensitively — the accessor and the engine agree.
|
inlineconstexpr |
Count non-overlapping matches without allocating result objects.
Prefer this over walking find_iter when only the count is needed. Region semantics match find_iter – pos is a start offset, not a slice (\\A / ^ still see the absolute position).
| [in] | text | The subject text. |
| [in] | pos | Byte offset to begin counting from (0 = start of text). |
| [in] | endpos | Exclusive end of the region; npos = end of text. |
|
inlineconstexprprivate |
count_matches over the trailing-lookaround walk, outlined.
OUTLINED AND COLD for the same reason basic_match_iterator::decide_batching is: this branch is taken only when pattern_hints::trailing_lookaround is armed, yet inline it put a SECOND fully inlined walk inside count_matches – the function every throughput measurement runs. That made count_matches large enough to sit on a codegen cliff: adding a single branch to the batched dispatch (no new function body, eligibility already outlined) recompiled it from 610 to 606 instructions, and the campaign that measured that state charged single [a-z] +10.7 %, \b\w+\b +4.0 %, \w+ +3.7 %, \w{2,} +3.2 % and fields [^,]+ +2.8 %, all above their own floors at 24 of 24 draws, on rows whose own code was byte-identical. The toll was not the change – it was this function being re-decided.
| [in] | region | The already-clamped subject. |
| [in] | pos | Where the walk starts. |
|
inlineconstexprprivate |
count_matches's walk: the ordinary one, run MATCHING-ONLY.
OUTLINED FIRST, AT ZERO BEHAVIOUR, AND JUDGED BEFORE ANYTHING WAS PUT IN IT. Adding a single branch to count_matches once recompiled it from 610 to 606 instructions and charged single [a-z] +10.7 %, \b\w+\b +4.0 %, \w+ +3.7 % and fields [^,]+ +2.8 %, all above their floors at 24 of 24 draws, on rows whose own code was byte-identical: the toll was that function being re-decided, not the branch. So the container went in alone and measured flat over 26 rows (medians -0.3 % to +0.8 %, 0 rows REAL) before this policy was added, which is why the policy needs no branch in count_matches at all.
THE POLICY. This function returns a NUMBER: no caller can observe a capture group, so writing them is pure loss. The walk therefore runs on a private copy of the program whose detail::pattern_hints::capture_free_walk is set — the same walk (?:...)-only patterns already get, where a thread's whole capture state is group 0's start in one scalar and the refcounted COW pool is never touched. On a capture-heavy pattern that takes the general VM, the increfs and copy-on-writes drop to ZERO while the VM steps exactly the same positions. That last part is the point — the walk is identical, only its bookkeeping is gone.
ONE FIELD, DELIBERATELY. slot_count is left alone even though the walk now fills only two slots: the batched span routes arm on slot_count == 2, so lowering it would ROUTE the pattern somewhere else and the measurement would be of a different engine. The same trap in reverse is what made the census's headline finding an illusion: (?:foo|bar)+baz is far cheaper than (foo|bar)+baz, but the second is a different PROGRAM taking a different route, and its VM steps an order of magnitude fewer positions. No walk flag can produce that; rewriting a user's groups to non-capturing at compile time might, and is a separate question with its own answers to give.
The structural condition is still asked (detail::capture_free_walk_structural) rather than assumed: it is a property of the program, and a program whose save 0 can be skipped would give a wrong answer, not a slow one. What this drops is the other half of the compiler's guard — no save past slot 1, and slot_count == 2 — which exists to protect captures nobody here is going to read.
THE FLAG IS SET BY THE RANGE, NOT HERE, and that is a measured requirement rather than a preference. Mutating a local view and handing it over costs a SECOND copy of a program_view, a fixed per-call cost with no proportional work behind it – flat in the subject length. The canonical rows never saw it: they measure this surface as THROUGHPUT on multi-kilobyte subjects, where one fixed copy amortises under the noise floor. Passing the intent instead of a mutated view leaves exactly find_iter's one copy.
noinline but NOT cold, unlike count_trailing_la – that branch is taken only when a hint is armed, this one is the ordinary path.
| [in] | text | The subject. |
| [in] | pos | Where the walk starts. |
| [in] | endpos | Region end, as find_iter takes it. |
|
inlinestaticconstexprprivate |
Hands a result the name context it will need after this regex is gone.
Taken and returned by value so the prvalue from run is constructed straight into the parameter and named-returned out: the rvalue overloads pay no move for going through here.
| [in] | result | The freshly run result. |
|
inlineconstexprprivate |
Appends replacement to out, substituting group references.
An invalid or out-of-range reference is an error (Python's rule), not left in place. The template spelling is ECMAScript / std::regex: $1, not \1.
| [in,out] | out | The output string to append to. |
| [in] | match | The match supplying the captured groups. |
| [in] | replacement | The replacement template ($$, $&, $1, ${name}). |
| real::regex_error | on a malformed or out-of-range reference. |
|
inlineconstexpr |
find_all overload for string literals.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
All matches, eagerly (like Python re.findall, but full results).
Lvalue-only, same reason as find_iter. High match counts allocate one result per hit; prefer count_matches when only the number matters, and find_iter when you can stream.
| [in] | text | The subject text (must outlive the results). |
|
inlineconstexpr |
find_iter overload for string literals.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
Lazy range over all non-overlapping matches (Python re.finditer).
Only callable on an lvalue regex: a C++20 range-for would dangle if the regex were a temporary (the range initializer dies before the loop body), so the rvalue overloads are deleted.
| [in] | text | The subject text (must outlive the range). |
|
inlineconstexpr |
Region-aware find_iter: iterate matches within [pos, endpos) (Python finditer with pos / endpos). endpos truncates the subject to a view so iteration stops at it; pos is the start, not a slice (see run). Byte offsets; endpos defaults to the end of text.
| [in] | text | Subject. |
| [in] | pos | Byte offset iteration starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
Experimental leftmost-**longest** find_iter: iterate matches with POSIX (leftmost-longest) bounds rather than the default leftmost-first — the iterator twin of search_longest, sharing its prototype status. Region semantics match find_iter — endpos truncates the subject to a view, pos is the start (not a slice). Byte offsets; captures are the winning thread's, not POSIX submatch. Every fast path is bypassed.
| [in] | text | Subject. |
| [in] | pos | Byte offset iteration starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
fullmatch overload for string literals.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
fullmatch on a temporary regex, string-literal overload.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
Match the entire text (Python re.fullmatch).
| [in] | text | The subject text (must outlive the result). |
|
inlineconstexpr |
fullmatch on a temporary regex; the result owns its name context.
| [in] | text | The subject text (must outlive the result). |
|
inlineconstexpr |
Region-aware fullmatch: the whole region [pos, endpos) must match.
| [in] | text | Subject. |
| [in] | pos | Byte offset the region starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
Region-aware fullmatch on a temporary regex; the result owns its name context.
| [in] | text | Subject. |
| [in] | pos | Byte offset the region starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
Returns the number of capturing groups (excluding group 0).
|
inlineconstexpr |
Resolves a group name to its number.
| [in] | name | The group name. |
|
inlineconstexprnoexcept |
Whether first-byte filtering is useful for this pattern.
true iff every non-empty match provably begins with a byte from a known set, so may_start_with can reject positions. false when a zero-length match is possible (or the set is empty) — then may_start_with is true for every byte and the filter buys nothing. This is the same set the engine's own prefilter uses, exposed for embedders (e.g. a lexer's rule dispatch).
true if the first-byte set is usable.
|
inlineconstexpr |
match overload for string literals.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
match on a temporary regex, string-literal overload.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
Match anchored at the start of text (Python re.match).
| [in] | text | The subject text (must outlive the result). |
matched() / operator bool).
|
inlineconstexpr |
match on a temporary regex; the result owns its name context.
| [in] | text | The subject text (must outlive the result). |
|
inlineconstexpr |
Region-aware match: anchored at pos within text[0:endpos] (Python re.match with pos / endpos). Byte offsets; pos is not a slice (see run — \A fails at pos > 0); endpos defaults to the end of text.
| [in] | text | Subject. |
| [in] | pos | Byte offset the match must start at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
pos.
|
inlineconstexpr |
Region-aware match on a temporary regex; the result owns its name context.
| [in] | text | Subject. |
| [in] | pos | Byte offset the match must start at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexprnoexcept |
Whether a non-empty match can begin with byte (sound, conservative).
A false result is a guarantee: no non-empty match of this pattern begins with byte. A true result is a conservative superset — it does not promise a match actually starts there. When first-byte filtering is not usable (has_first_byte_set is false, i.e. an empty match is possible), this returns true for every byte, so it is safe to use on its own.
| [in] | byte | The candidate leading byte. |
false only when byte can never start a non-empty match.
|
inlineconstexprprivate |
Returns its name, sliced from the pattern text.
| [in] | named_group | A named group. |
|
inlineconstexpr |
The index-th named group, in declaration order.
| [in] | index | Position in [0, named_group_count()); out of range is undefined, as for any indexed accessor on this class. |
|
inlineconstexpr |
How many named groups the pattern declares.
With named_group_at, this is the allocation-free way to enumerate them. named_groups materialises a vector on every call, so a caller walking the names one at a time — which is what a name-by-number ABI does — paid a fresh vector per name. Reading the program's own span instead removes the allocation entirely, a constant factor that grows with the name count.
|
inlineconstexpr |
All named groups as (name, number) pairs, in declaration order.
|
inlineconstexpr |
Returns the pattern text this regex was compiled from.
|
inlineconstexpr |
The raw compiled program, for embedders (advanced).
Lets an embedder (e.g. the Python binding) drive detail::pike_vm with caller-owned reusable scratch. Valid as long as this regex is alive.
|
inlineconstexpr |
Replaces matches in text (ECMAScript / std::regex_replace $1).
The replacement may reference groups: $$ → '$', $& or $0 → whole match, $1 …, and ${name}. This is not Python re.sub (\1 / \g<name>) — that spelling is the Python and Go bindings. Returns an owning string, so a temporary text is fine here.
| [in] | text | The subject text. |
| [in] | replacement | The replacement template. |
| [in] | max_count | Maximum replacements (0 = all). |
| real::regex_error | on a malformed group reference in replacement. |
|
inlineconstexprprivate |
Runs a single match attempt from offset 0 (backs match/search/fullmatch).
| [in] | text | The subject text. |
| [in] | mode | The anchoring mode. |
|
inlineconstexprprivate |
Region-aware single attempt: match over text[0:endpos] starting at pos.
pos is the VM start offset, not a slice — zero-width assertions still see the absolute position, so \A and ^ (non-multiline) fail at pos > 0, matching Python re. endpos truncates the subject to a view (no copy), so $ / \Z treat it as the end. endpos is clamped to the text length; pos > endpos yields no match. Capture offsets are absolute byte offsets in text.
| [in] | text | The full subject (offsets are relative to it; must outlive the result). |
| [in] | pos | Byte offset to start matching at. |
| [in] | endpos | Byte offset of the exclusive region end; npos = end of text. |
| [in] | mode | The anchoring mode. |
| [in] | sem | Match semantics: leftmost-first (default) or the experimental leftmost-longest. |
text.
|
inlineconstexpr |
search overload for string literals.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
search on a temporary regex, string-literal overload.
| [in] | text | NUL-terminated text. |
|
inlineconstexpr |
Leftmost match anywhere in text (Python re.search).
| [in] | text | The subject text (must outlive the result). |
|
inlineconstexpr |
search on a temporary regex; the result owns its name context.
| [in] | text | The subject text (must outlive the result). |
|
inlineconstexpr |
Region-aware search: leftmost match within [pos, endpos).
| [in] | text | Subject. |
| [in] | pos | Byte offset the search starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
Region-aware search on a temporary regex; the result owns its name context.
| [in] | text | Subject. |
| [in] | pos | Byte offset the search starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inline |
EXPERIMENTAL, opt-in: a single leftmost-**longest** search (POSIX / RE2 set_longest_match), the default leftmost-first semantics left untouched. Among matches at the leftmost start it returns the longest; a lazy quantifier therefore behaves greedily, and captures are the leftmost-first thread's at that longest bound (not POSIX submatch). Runs on the general Pike loop (the first-match DFA / inner-literal fast paths are bypassed). A prototype for the match_semantics arc — not yet a stable API. Its iteration twin is find_iter_longest.
| [in] | text | Subject. |
|
inline |
Region-aware form of search_longest — leftmost-longest search within [pos, endpos). pos is the start (not a slice, per run); endpos truncates the subject. Byte offsets.
| [in] | text | Subject. |
| [in] | pos | Byte offset the search starts at. |
| [in] | endpos | Byte offset the region ends at; defaults to the end of text. |
|
inlineconstexpr |
split overload for string literals.
| [in] | text | NUL-terminated text. |
| [in] | max_splits | Max splits. |
|
inlineconstexpr |
Splits text on matches (Python re.split).
Each capturing group's text is inserted after its split (an unset group yields an empty view, where Python would use None).
| [in] | text | The subject text (must outlive the returned views). |
| [in] | max_splits | Maximum splits (0 = split everywhere). |
|
inlineconstexprnoexcept |
The single byte every non-empty match must begin with, if unique.
if / def); std::nullopt for zero or several.