14#ifndef REAL_STORAGE_HPP
15#define REAL_STORAGE_HPP
45 template <std::
size_t N>
61 for (std::size_t i = 0; i < N; ++i) {
69 [[nodiscard]]
constexpr std::string_view
view()
const
89 template <
typename T, std::
size_t Cap>
102 throw std::length_error(
"static_vec overflow");
126 throw std::length_error(
"static_vec overflow");
128 for (std::size_t i = 0; i <
count; ++i) {
137 [[nodiscard]]
constexpr std::size_t
size()
const
145 [[nodiscard]]
constexpr bool empty()
const
165 [[nodiscard]]
constexpr const T&
operator[](std::size_t i)
const
173 [[nodiscard]]
constexpr T&
back()
175 assert(
size_ > 0 &&
"back() on an empty static_vec");
184 assert(
size_ > 0 &&
"pop_back() on an empty static_vec");
218 template <
typename T, std::
size_t InlineCapacity>
221 static_assert(InlineCapacity > 0,
"InlineCapacity must be positive");
225 static_assert(std::is_trivially_destructible_v<T>,
226 "small_vec is for trivially-destructible types only");
269 if (std::is_constant_evaluated()) {
299 if (!std::is_constant_evaluated()) {
332 if constexpr (std::is_trivially_copyable_v<T>) {
333 if (!std::is_constant_evaluated()) {
334 std::memcpy(dest, src,
count *
sizeof(T));
340 for (std::size_t i = 0; i <
count; ++i) {
341 if constexpr (Move) {
342 std::construct_at(&dest[i], std::move(src[i]));
345 std::construct_at(&dest[i], src[i]);
366 const std::size_t inline_count {other.
size_ <= InlineCapacity ? other.
size_ : InlineCapacity};
377 if (std::is_constant_evaluated()) {
391 const std::size_t new_cap {(current > (std::size_t)-1 / 2) ? (std::size_t)-1 : current * 2};
413 if (!std::is_constant_evaluated()) {
427 if (std::is_constant_evaluated()) {
428 throw std::bad_alloc {};
432 if (std::is_constant_evaluated()) {
460 if (std::is_constant_evaluated()) {
461 throw std::bad_alloc {};
465 for (std::size_t i = 0; i <
count; ++i) {
466 if (std::is_constant_evaluated()) {
480 std::construct_at(&
data_[i], value);
489 [[nodiscard]]
constexpr std::size_t
size() const noexcept
497 [[nodiscard]]
constexpr bool empty() const noexcept
507 [[nodiscard]]
constexpr T&
operator[](std::size_t i)
noexcept
509 if (std::is_constant_evaluated()) {
520 [[nodiscard]]
constexpr const T&
operator[](std::size_t i)
const noexcept
522 if (std::is_constant_evaluated()) {
539 [[nodiscard]]
constexpr T&
back() noexcept
541 assert(
size_ > 0 &&
"back() on an empty small_vec");
542 if (std::is_constant_evaluated()) {
551 [[nodiscard]]
constexpr const T&
back() const noexcept
553 assert(
size_ > 0 &&
"back() on an empty small_vec");
554 if (std::is_constant_evaluated()) {
568 assert(
size_ > 0 &&
"pop_back() on an empty small_vec");
577 constexpr void reserve(std::size_t new_capacity)
582 if (std::is_constant_evaluated()) {
583 throw std::bad_alloc {};
585 T * new_data {
static_cast<T*
>(::operator
new(new_capacity *
sizeof(T)))};
587 transfer_range<false>(old_data,
size_, new_data);
601 :
size_(other.size_),
607 other.storage_.heap_ptr =
nullptr;
608 other.is_heap_ =
false;
610 other.capacity_ = InlineCapacity;
613 transfer_inline_from<true>(other);
616 other.refresh_data();
626 if (
this != &other) {
633 other.storage_.heap_ptr =
nullptr;
634 other.is_heap_ =
false;
636 other.capacity_ = InlineCapacity;
639 transfer_inline_from<true>(other);
642 other.refresh_data();
655 if (std::is_constant_evaluated()) {
656 throw std::bad_alloc {};
664 transfer_inline_from<false>(other);
676 if (
this != &other) {
688 transfer_inline_from<false>(other);
713 basic_thread_list<small_vec<std::int32_t, 64>,
714 small_vec<std::size_t, 256>,
715 std::vector<std::uint64_t>>,
716 small_vec<eps_entry, 32>>
750 return {.pattern_text = std::string(
pattern),
752 .effective_flags = effective};
768 [[nodiscard]]
constexpr std::string_view
pattern()
const
792 template <fixed_
string Pat, flags F = flags::none>
810 if (!prog.lookarounds.empty()) {
813 throw regex_error(
"static_regex does not support lookarounds yet (use real::regex)", 0);
826 template <
typename T, std::
size_t N,
typename Vec>
827 static constexpr std::array<T, N>
take(
const Vec& source)
829 std::array<T, N> result {};
830 for (std::size_t i = 0; i <
N; ++i) {
831 result[i] = source[i];
847 static constexpr std::array<instr, code_size>
code {take<instr, code_size>(
build().
code)};
848 static constexpr std::array<char_class, class_count>
classes =
850 static constexpr std::array<named_group, name_count>
names =
852 static constexpr std::array<cp_class, cp_class_count>
cp_classes =
854 static constexpr std::array<code_range, cp_range_count>
cp_ranges =
875 basic_thread_list<static_vec<std::int32_t, code_size>,
876 static_vec<std::size_t, code_size>,
877 static_vec<std::uint64_t, code_size>>,
878 static_vec<eps_entry, (3 * code_size) + 4>>
897 .prefix_classes = {},
898 .prefix_cp_classes = {},
899 .prefix_cp_ranges = {},
909 [[nodiscard]]
constexpr std::string_view
pattern()
const
Pattern text → AST, via a constexpr recursive-descent parser.
Small-buffer-optimized vector for the dynamic hot paths.
bool is_heap_
True once spilled to the heap.
constexpr void transfer_inline_from(const small_vec &other)
Transfers other's inline elements into this vector's inline buffer.
constexpr void assign(std::size_t count, const T &value)
Resizes to count copies of value.
constexpr bool empty() const noexcept
Returns true if empty.
std::size_t size_type_
Size type (for std-container API compat).
constexpr small_vec() noexcept
Constructs an empty vector in the inline state.
constexpr void refresh_data() noexcept
Refreshes data_ to the active storage base (run time only).
constexpr const T & back() const noexcept
Returns const reference to the last element. Precondition: the vector is non-empty.
constexpr void reserve(std::size_t new_capacity)
Ensures capacity for at least new_capacity elements (heap-backed).
T value_type
Element type.
constexpr T & back() noexcept
Returns reference to the last element. Precondition: the vector is non-empty.
constexpr const T * inline_data() const noexcept
Returns const pointer to the inline buffer.
constexpr ~small_vec()
Destroys elements and frees any heap block.
constexpr std::size_t size() const noexcept
Returns the number of elements.
union real::detail::small_vec::Storage storage_
constexpr void cleanup() noexcept
Frees the heap block, if any (run-time only). T is trivially destructible (see the class static_asser...
constexpr T & operator[](std::size_t i) noexcept
Returns reference to the element at i.
void extend_capacity()
Doubles the capacity (saturating), spilling to the heap as needed.
constexpr void transfer_range(const T *src, std::size_t count, T *dest)
Copies or moves count elements from src to dest.
constexpr small_vec & operator=(small_vec &&other) noexcept
Move assignment.
constexpr void push_back(const T &value)
Appends value, growing to the heap if the inline buffer is full.
constexpr small_vec(const small_vec &other)
Copy constructor (needed for vector<match_result> in find_all).
constexpr void clear() noexcept
Removes all elements (capacity and heap state unchanged).
constexpr small_vec(small_vec &&other) noexcept
Move constructor: steals other's heap block or moves inline elements.
std::size_t capacity_
Current capacity.
constexpr T * inline_data() noexcept
Returns pointer to the inline buffer.
std::size_t size_
Number of elements in use.
constexpr const T & operator[](std::size_t i) const noexcept
Returns const reference to the element at i.
constexpr void pop_back() noexcept
Removes the last element. Precondition: the vector is non-empty.
constexpr small_vec & operator=(const small_vec &other)
Copy assignment.
Fixed-capacity vector backed by an inline array (no heap).
constexpr void pop_back()
Removes the last element. Precondition: the vector is non-empty.
constexpr void clear()
Removes all elements (capacity unchanged).
constexpr const T & operator[](std::size_t i) const
Returns const reference to the element at i.
std::size_t size_
Number of elements in use.
std::array< T, Cap > data_
Inline element storage.
constexpr std::size_t size() const
Returns the number of elements.
constexpr T & operator[](std::size_t i)
Returns reference to the element at i.
constexpr void assign(std::size_t count, const T &value)
Resizes to count copies of value.
constexpr void push_back(const T &value)
Appends value.
constexpr T & back()
Returns reference to the last element. Precondition: the vector is non-empty.
constexpr bool empty() const
Returns true if empty.
AST → NFA program, via Thompson construction.
constexpr dynamic_program compile(const ast &tree, flags compile_flags)
Compiles tree to an NFA program (convenience over compiler).
constexpr ast parse(std::string_view pattern, flags initial_flags=flags::none)
Parses pattern into an ast (convenience over parser).
constexpr bool has_flag(flags value, flags flag)
Tests whether flag is set in value.
flags
Compilation flags, mirroring Python's re.I, re.M and re.S.
@ bytes
Binary mode: . and [^…] match raw bytes, not codepoints.
@ ascii
ASCII mode (re.A): \d \w \s \b stay ASCII and icase folds ASCII only, even in text mode....
The Pike VM — a Thompson NFA simulation — and its fast paths.
Compiled form of a pattern and the public flags / error types.
A parsed pattern: the node pool plus side tables.
flags inline_flags
Flags from a leading (?ims).
Reusable VM scratch state.
Owning, heap-allocated program: the storage backing real::regex.
std::vector< cp_class > cp_classes
Match-time code-point classes (for klass_cp).
pattern_hints hints
Search-acceleration hints.
std::uint16_t slot_count
2 * (capture groups + 1).
std::vector< instr > code
The instruction stream (main program + lookaround sub-program regions).
constexpr program_view view() const
Returns a non-owning program_view over this program.
std::vector< code_range > cp_ranges
Flat range buffer the cp_class slices index into.
std::vector< char_class > classes
Interned character classes.
std::vector< named_group > names
Named capture groups.
VM scratch state: SBO thread lists, working slots and eps stack.
capture_pool pool
OPT D1: copy-on-write capture blocks (heap-backed).
std::optional< lazy_dfa > fwd_dfa
OPT lazy-DFA: forward pass (cache persists across a find_iter).
const void * il_prefix_for
IL: the prefix program il_prefix_rev was built for.
std::optional< reverse_dfa > il_prefix_rev
IL: the inner-literal prefix reverse DFA (built once per program).
std::optional< reverse_dfa > rev_dfa
OPT lazy-DFA: the reverse start-finder.
lookaround_scratch lookaround
Isolated sub-scratch for bounded lookaround evaluation.
const void * il_text
IL: the haystack il_abandoned refers to.
bool il_abandoned
IL: a linearity guard tripped on this haystack — stay on the core.
const void * dfa_program
The program the DFAs were built for.
Storage policy backing real::regex: heap, sized once at run time.
static constexpr dynamic_storage compile(std::string_view pattern, flags compile_flags)
Parses and compiles pattern with flags compile_flags.
std::string pattern_text
The original pattern text.
dynamic_program program
The compiled program.
constexpr program_view view() const
Returns a non-owning view of the compiled program.
constexpr flags compiled_flags() const
Returns the effective flags (constructor flags merged with (?ims)).
flags effective_flags
Constructor flags merged with any (?ims).
constexpr std::string_view pattern() const
Returns the original pattern text.
static constexpr bool is_compile_time
Selects the runtime constructor.
detail::regex_immutables immut_
Per-regex lazy-DFA/one-pass cache, built once (thread-safe) and shared by every search on this regex ...
Reusable, isolated scratch for one level of lookaround evaluation (dynamic only).
Search-acceleration hints extracted from a compiled program.
regex_immutables * immut
Per-regex DFA/one-pass cache (dynamic storage only; else null).
std::span< const instr > code
The instruction stream (main + lookaround regions).
The per-regex immutable cache the router shares across every find_iter on a regex: the byte- program ...
Active member (inline buffer or heap pointer) per is_heap_ state.
VM scratch state, all fixed-capacity (zero heap).
basic_capture_pool< static_vec< std::size_t, max_blocks *slot_count >, static_vec< std::int32_t, max_blocks >, static_vec< std::uint32_t, max_blocks > > pool
COW capture blocks (zero heap).
Storage policy backing real::static_regex: compile-time, stateless.
static constexpr std::size_t name_count
Named-group count.
static constexpr bool is_compile_time
Selects the default constructor.
static constexpr std::size_t max_blocks
static constexpr std::array< instr, code_size > code
The program.
static constexpr std::array< char_class, class_count > classes
Interned classes.
constexpr flags compiled_flags() const
Returns the effective flags.
static constexpr std::uint16_t slot_count
2*(groups+1).
static constexpr dynamic_program build()
Returns the freshly built program (used for both measuring and filling).
constexpr program_view view() const
Returns a non-owning view of the compile-time program.
static constexpr std::size_t class_count
Distinct class count.
static constexpr std::array< cp_class, cp_class_count > cp_classes
Code-point classes.
static constexpr std::array< named_group, name_count > names
Named groups.
static constexpr std::size_t code_size
Instruction count.
static constexpr flags effective_flags
Flags merged with (?ims).
static constexpr std::array< T, N > take(const Vec &source)
Copies the first N elements of v into a fixed array.
constexpr std::string_view pattern() const
Returns the pattern text.
static constexpr pattern_hints hints
Search hints.
static constexpr std::size_t cp_range_count
Total code-point ranges.
static constexpr std::array< code_range, cp_range_count > cp_ranges
Flat range buffer.
static constexpr std::size_t cp_class_count
Code-point class count (klass_cp).
A fixed-size string usable as a non-type template parameter.
constexpr std::string_view view() const
Returns a view of the string, excluding the trailing NUL.
constexpr fixed_string(const char(&literal)[N])
Captures a string literal.
char data[N]
The captured characters, including the trailing NUL.
inline_block inline_buffer
Inline storage (when not heap).
constexpr ~Storage()
Destruction handled by cleanup.
Storage(const Storage &)=delete
constexpr Storage() noexcept
Starts in the inline state.
Storage(Storage &&)=delete
Storage & operator=(Storage &&)=delete
T * heap_ptr
Heap storage (when is_heap_).
Storage & operator=(const Storage &)=delete
REAL's version macros and the C++20 language-standard guard.