REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
Loading...
Searching...
No Matches
real::basic_match_result< SlotStorage, NameOwner > Class Template Reference

The result of a match attempt: success, spans and captures. More...

#include <real.hpp>

Collaboration diagram for real::basic_match_result< SlotStorage, NameOwner >:
[legend]

Public Member Functions

constexpr basic_match_result ()=default
 Constructs an empty (non-matched) result.
 
constexpr basic_match_result (std::string_view text, SlotStorage &&slots, bool matched, std::string_view pattern, std::span< const detail::named_group > names)
 Constructs a result from raw slots (used internally by the engine).
 
template<typename OtherOwner >
requires (!std::is_same_v<OtherOwner, NameOwner>)
constexpr basic_match_result (basic_match_result< SlotStorage, OtherOwner > other)
 Engine-internal: adopts the fields of the borrowing twin, to be detached next.
 
constexpr basic_match_result (std::string_view text, std::string_view pattern, std::span< const detail::named_group > names)
 Engine-internal: an empty, unmatched result whose slot storage is built IN PLACE.
 
constexpr SlotStorage & engine_slots () noexcept
 Engine-internal: the slot storage, for the engine to fill in place.
 
constexpr void engine_set_matched (bool matched) noexcept
 Engine-internal: records whether the fill that just ran produced a match.
 
constexpr void detach_from_regex ()
 Engine-internal: stop borrowing the regex's name tables, because it is about to die.
 
template<bool Cascade, typename Vm >
constexpr bool engine_refill (Vm &vm, std::string_view text, std::size_t pos, detail::run_mode mode, std::size_t forbid, std::string_view pattern, std::span< const detail::named_group > names)
 Engine-internal: re-run the search into this result's OWN slot buffer, reusing its capacity. Not part of the public API.
 
constexpr void bind_context (std::string_view text, std::string_view pattern, std::span< const detail::named_group > names)
 Binds the invariant context (subject, pattern, named groups) once. For an iterator that refills the same result many times, these never change within a walk — set them here, not per match.
 
template<bool Cascade, typename Vm >
constexpr bool engine_refill_hot (Vm &vm, std::string_view text, std::size_t pos, detail::run_mode mode, std::size_t forbid, match_semantics sem=match_semantics::first)
 Per-match refill for an iterator whose context is already bound via bind_context runs the VM and records only the outcome (the invariant fields are already set), the find_iter hot path.
 
template<typename Vm >
constexpr void engine_refill_span (Vm &vm, std::size_t s, std::size_t e)
 Refill from a span the engine already found in a batch, bypassing the VM entirely.
 
template<bool Cascade, typename Vm >
constexpr bool engine_refill_trailing_la (Vm &vm, std::string_view text, std::size_t pos)
 Cold path for TrailingLA walks only (never referenced from pure walks).
 
constexpr bool matched () const
 Returns true if the attempt matched.
 
constexpr operator bool () const
 Returns true if the attempt matched (explicit bool conversion).
 
constexpr std::size_t size () const
 Returns the number of groups, including group 0 (the whole match).
 
constexpr std::size_t start (std::size_t group=0) const
 Start byte offset of a group.
 
constexpr std::size_t end (std::size_t group=0) const
 End byte offset (exclusive) of a group.
 
constexpr std::string_view operator[] (std::size_t group) const
 View of a group's matched text.
 
constexpr std::string_view str (std::size_t group=0) const
 View of a group's matched text — std::smatch's spelling for operator[].
 
constexpr std::size_t group_index (std::string_view name) const
 Resolves a group name to its number.
 
constexpr std::size_t start (std::string_view name) const
 Returns its start offset, or npos if unknown.
 
constexpr std::size_t end (std::string_view name) const
 Returns its end offset, or npos if unknown.
 
constexpr std::string_view operator[] (std::string_view name) const
 Returns its matched text, empty if unknown/unset.
 
constexpr std::span< const std::size_t > spans () const noexcept
 The capture slots as one flat [start0, end0, start1, end1, …] view.
 

Private Attributes

std::string_view text_
 The searched text.
 
SlotStorage slots_
 Flattened capture slots.
 
bool matched_ {}
 Whether a match occurred.
 
std::string_view pattern_
 Pattern text (for named lookups).
 
std::span< const detail::named_groupnames_
 
NameOwner owner_ {}
 

Friends

template<typename , typename >
class basic_match_result
 The twin specialisation reads these fields to adopt them; nothing else does.
 

Detailed Description

template<typename SlotStorage, typename NameOwner = detail::borrowed_names>
class real::basic_match_result< SlotStorage, NameOwner >

The result of a match attempt: success, spans and captures.

Group views point into the searched text, which must outlive the result — the rvalue std::string overloads on the regex are deleted so the common dangling mistake is a compile error.

Named-group lookups need the regex's pattern text and name table. A result from a live regex borrows both. A result from a temporary regex is real::basic_regex::owning_result_type — the same class, owning those tables — so names still resolve after the regex dies. find_iter and find_all have no such twin: they are deleted on an rvalue regex.

Template Parameters
SlotStorageThe capture-slot container (vector- or static-backed), supplied by the storage policy.
NameOwnerHow name tables are held: borrowed from a live regex, or owned after a temporary regex dies.

Constructor & Destructor Documentation

◆ basic_match_result() [1/3]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr real::basic_match_result< SlotStorage, NameOwner >::basic_match_result ( std::string_view  text,
SlotStorage &&  slots,
bool  matched,
std::string_view  pattern,
std::span< const detail::named_group names 
)
inlineconstexpr

Constructs a result from raw slots (used internally by the engine).

Parameters
[in]textThe searched text (borrowed; must outlive the result).
[in]slotsFlattened capture slots (byte offsets, npos for unset).
[in]matchedWhether a match occurred.
[in]patternThe pattern text (for named-group resolution).
[in]namesThe regex's named-group table (borrowed).

◆ basic_match_result() [2/3]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
template<typename OtherOwner >
requires (!std::is_same_v<OtherOwner, NameOwner>)
constexpr real::basic_match_result< SlotStorage, NameOwner >::basic_match_result ( basic_match_result< SlotStorage, OtherOwner >  other)
inlineexplicitconstexpr

Engine-internal: adopts the fields of the borrowing twin, to be detached next.

A template, and constrained, so that it exists only for the owning specialisation – the borrowing one is what every walk and every attempt on a live regex yields, and it must stay exactly the type it was.

Taken by value: the caller hands over a prvalue, so nothing is copied, and the slots move out of the parameter rather than out of a subobject of a reference.

Template Parameters
OtherOwnerThe source's name owner, necessarily not this one's.
Parameters
[in]otherThe freshly run result to take over.

◆ basic_match_result() [3/3]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr real::basic_match_result< SlotStorage, NameOwner >::basic_match_result ( std::string_view  text,
std::string_view  pattern,
std::span< const detail::named_group names 
)
inlineconstexpr

Engine-internal: an empty, unmatched result whose slot storage is built IN PLACE.

Paired with engine_slots and engine_set_matched, this is what lets basic_regex::run hand the engine the FINAL slot storage instead of filling a local and moving it in. The move it removes was the last bulk copy per call: gcc lowered it to a rep movsq worth 12.02 % of the inlined per-call path (small_vec::transfer_range<true> through transfer_inline_from), and rep movs pays a fixed startup whatever the volume — which for a groupless pattern is sixteen bytes. run() has a single return statement, so the result is NRVO-constructed in the caller's storage and the engine writes straight into it.

Parameters
[in]textThe searched text (borrowed; must outlive the result).
[in]patternThe pattern text (for named-group resolution).
[in]namesThe regex's named-group table (borrowed).

Member Function Documentation

◆ bind_context()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr void real::basic_match_result< SlotStorage, NameOwner >::bind_context ( std::string_view  text,
std::string_view  pattern,
std::span< const detail::named_group names 
)
inlineconstexpr

Binds the invariant context (subject, pattern, named groups) once. For an iterator that refills the same result many times, these never change within a walk — set them here, not per match.

Parameters
[in]textThe subject the walk runs over.
[in]patternThe pattern text, for diagnostics and group naming.
[in]namesThe pattern's named groups.

◆ detach_from_regex()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr void real::basic_match_result< SlotStorage, NameOwner >::detach_from_regex ( )
inlineconstexpr

Engine-internal: stop borrowing the regex's name tables, because it is about to die.

search, match and fullmatch are callable on a temporary regex, and must stay so – the one-expression form (real::regex{"a+"}.search(text).matched()) is safe, since the temporary outlives the full-expression, and it is the shape most callers write. What is NOT safe is the result outliving that temporary: group_index reads the pattern text and the named-group table, both of which the regex owns. This copies them into the result instead, so a result from an rvalue regex resolves names correctly for as long as it exists.

The borrowed views are cleared either way: with named groups owner_ becomes the source of truth (which is what keeps the implicit copy constructor correct – a copy deep-copies the box and reads its OWN, rather than inheriting views into the original's), and without them there is nothing to copy, but a dangling view nobody dereferences would still be one.

A no-op on the compile-time policy, whose tables have static storage duration.

◆ end() [1/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::end ( std::size_t  group = 0) const
inlineconstexpr

End byte offset (exclusive) of a group.

Parameters
[in]groupGroup number (0 = whole match).
Returns
The offset, or real::npos if the group did not participate.

◆ end() [2/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::end ( std::string_view  name) const
inlineconstexpr

Returns its end offset, or npos if unknown.

Parameters
[in]nameGroup name.
Returns
Its end offset, or npos if unknown.

◆ engine_refill()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
template<bool Cascade, typename Vm >
constexpr bool real::basic_match_result< SlotStorage, NameOwner >::engine_refill ( Vm &  vm,
std::string_view  text,
std::size_t  pos,
detail::run_mode  mode,
std::size_t  forbid,
std::string_view  pattern,
std::span< const detail::named_group names 
)
inlineconstexpr

Engine-internal: re-run the search into this result's OWN slot buffer, reusing its capacity. Not part of the public API.

The match iterator holds one result and refreshes it in place each step. vm.run fills the slots via assign, which reuses the existing capacity, so a match-dense iteration allocates the slot vector once instead of once per match — the measured per-match cost (a fresh allocation is ~5x a reused one). A user-held copy of a previous match stays independent: copying a result deep-copies its slots, so refilling this one never disturbs it.

Template Parameters
CascadeSelect the memchr-cascade class-run variant (chosen once per walk).
VmThe Pike VM type (kept a template to avoid a header cycle).
Parameters
[in]vmThe VM to run.
[in]textThe searched text (borrowed).
[in]posStart offset for the search.
[in]modeThe run mode.
[in]forbidThe empty-match forbid-until offset.
[in]patternThe pattern text (for named-group resolution).
[in]namesThe regex's named-group table (borrowed).
Returns
Whether a match occurred.

◆ engine_refill_hot()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
template<bool Cascade, typename Vm >
constexpr bool real::basic_match_result< SlotStorage, NameOwner >::engine_refill_hot ( Vm &  vm,
std::string_view  text,
std::size_t  pos,
detail::run_mode  mode,
std::size_t  forbid,
match_semantics  sem = match_semantics::first 
)
inlineconstexpr

Per-match refill for an iterator whose context is already bound via bind_context runs the VM and records only the outcome (the invariant fields are already set), the find_iter hot path.

Template Parameters
CascadeWhether the VM may take its memchr-cascade tail.
VmThe engine type, deduced.
Parameters
[in,out]vmThe engine to run.
[in]textThe subject.
[in]posByte offset to attempt at.
[in]modeAnchoring: full, prefix or search.
[in]forbidOffset at which a zero-length match is refused (the find_iter no-progress rule).
[in]semLeftmost-first or leftmost-longest.
Returns
True on a match; the slots hold it.

◆ engine_refill_span()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
template<typename Vm >
constexpr void real::basic_match_result< SlotStorage, NameOwner >::engine_refill_span ( Vm &  vm,
std::size_t  s,
std::size_t  e 
)
inlineconstexpr

Refill from a span the engine already found in a batch, bypassing the VM entirely.

Template Parameters
VmThe engine type, deduced.
Parameters
[in,out]vmThe engine, used only to reconstruct the slot layout for this span.
[in]sMatch start.
[in]eMatch end.

◆ engine_refill_trailing_la()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
template<bool Cascade, typename Vm >
constexpr bool real::basic_match_result< SlotStorage, NameOwner >::engine_refill_trailing_la ( Vm &  vm,
std::string_view  text,
std::size_t  pos 
)
inlineconstexpr

Cold path for TrailingLA walks only (never referenced from pure walks).

Template Parameters
CascadeWhether the VM may take its memchr-cascade tail.
VmThe engine type, deduced.
Parameters
[in,out]vmThe engine to run.
[in]textThe subject.
[in]posByte offset to attempt at.
Returns
True on a match; the slots hold it.

◆ engine_set_matched()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr void real::basic_match_result< SlotStorage, NameOwner >::engine_set_matched ( bool  matched)
inlineconstexprnoexcept

Engine-internal: records whether the fill that just ran produced a match.

Parameters
[in]matchedWhether a match occurred.

◆ engine_slots()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr SlotStorage & real::basic_match_result< SlotStorage, NameOwner >::engine_slots ( )
inlineconstexprnoexcept

Engine-internal: the slot storage, for the engine to fill in place.

Returns
A mutable reference to the flattened capture slots.

◆ group_index()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::group_index ( std::string_view  name) const
inlineconstexpr

Resolves a group name to its number.

Parameters
[in]nameThe group name.
Returns
The group number, or real::npos if unknown.

◆ matched()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr bool real::basic_match_result< SlotStorage, NameOwner >::matched ( ) const
inlineconstexpr

Returns true if the attempt matched.

Returns
Whether the attempt matched.

◆ operator bool()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr real::basic_match_result< SlotStorage, NameOwner >::operator bool ( ) const
inlineexplicitconstexpr

Returns true if the attempt matched (explicit bool conversion).

Returns
Whether the attempt matched.

◆ operator[]() [1/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::string_view real::basic_match_result< SlotStorage, NameOwner >::operator[] ( std::size_t  group) const
inlineconstexpr

View of a group's matched text.

Parameters
[in]groupGroup number (0 = whole match).
Returns
A view into the searched text, empty if the group is unset.

◆ operator[]() [2/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::string_view real::basic_match_result< SlotStorage, NameOwner >::operator[] ( std::string_view  name) const
inlineconstexpr

Returns its matched text, empty if unknown/unset.

Parameters
[in]nameGroup name.
Returns
Its matched text, empty if unknown/unset.

◆ size()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::size ( ) const
inlineconstexpr

Returns the number of groups, including group 0 (the whole match).

Returns
The group count.

◆ spans()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::span< const std::size_t > real::basic_match_result< SlotStorage, NameOwner >::spans ( ) const
inlineconstexprnoexcept

The capture slots as one flat [start0, end0, start1, end1, …] view.

For a caller that copies every group in one pass (the C ABI's spans buffer is this layout). Only meaningful on a matched result — an unmatched one carries whatever the last fill left. Prefer start / end when reading a single group; those return real::npos if it did not participate. Copy pairwise (spans[2g], spans[2g+1]).

Returns
A view of 2 * size() slot values; empty when there are no slots.

◆ start() [1/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::start ( std::size_t  group = 0) const
inlineconstexpr

Start byte offset of a group.

Parameters
[in]groupGroup number (0 = whole match).
Returns
The offset, or real::npos if the group did not participate.

◆ start() [2/2]

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::size_t real::basic_match_result< SlotStorage, NameOwner >::start ( std::string_view  name) const
inlineconstexpr

Returns its start offset, or npos if unknown.

Parameters
[in]nameGroup name.
Returns
Its start offset, or npos if unknown.

◆ str()

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
constexpr std::string_view real::basic_match_result< SlotStorage, NameOwner >::str ( std::size_t  group = 0) const
inlineconstexpr

View of a group's matched text — std::smatch's spelling for operator[].

Exactly operator[], under the name a caller arriving from std::regex writes first. Without it m.str(1) is a compile error that names an internal storage type and suggests nothing. Unlike std::smatch::str it returns a view rather than an owned string, so it never copies and the subject must outlive the result.

That difference bites on the NEXT line the same caller writes: std::string s = m.str(1); does not compile, because std::string_view converts to std::string explicitly. Spell it std::string s {m.str(1)}; when an owned copy is what you want.

Parameters
[in]groupGroup number (0 = whole match).
Returns
A view into the searched text, empty if the group is unset.

Member Data Documentation

◆ names_

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
std::span<const detail::named_group> real::basic_match_result< SlotStorage, NameOwner >::names_
private

Named-group table: borrowed, or owned via owner_.

◆ owner_

template<typename SlotStorage , typename NameOwner = detail::borrowed_names>
NameOwner real::basic_match_result< SlotStorage, NameOwner >::owner_ {}
private

Owns what pattern_ and names_ point at, once detach_from_regex has run; empty (and zero-sized) on the compile-time policy, null on every result that borrows.


The documentation for this class was generated from the following file: