|
REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
|
Reusable VM scratch state. More...
#include <pike.hpp>
Public Member Functions | |
| constexpr | basic_pike_state () noexcept |
| Value-initializes table and cp_page during constant evaluation only. | |
Public Attributes | |
| ThreadList | list_a |
| One of the two thread lists; the run rotates pointers, not indices. | |
| ThreadList | list_b |
| The other one — see list_a. | |
| EpsVec | stack |
| Epsilon-closure DFS stack. | |
| std::int32_t | table_class {-1} |
| Flat 256-byte membership table for the hot single-class scan, and the class index it was built for (-1 = none). | |
| std::array< std::uint8_t, 256 > | table |
| 1 where the byte is in table_class (filled on a class_table miss). | |
| std::int32_t | cp_page_class {-1} |
Membership bitmap for a cp_class over the 2-byte UTF-8 range [U+0080, U+07FF], and the class it was built for. European text lives almost entirely in this range (Latin, IPA, Greek, Cyrillic, Hebrew, Arabic…), so a 240-byte bitmap answers it in one load. Built once per class and reused across a find_all-style walk. | |
| std::array< std::uint64_t, 30 > | cp_page |
| 1 where the code point (U+0080..U+07FF) is a member (filled on a cp_page_table miss). | |
| const void * | rows_verified_for {nullptr} |
Program whose membership rows this state has already verified as filled. Lets a walk skip the two acquire loads class_table would otherwise do once per run() — see there. | |
| const std::uint8_t * | row_ptr {nullptr} |
| The verified byte row, cached so the hot path returns it without re-deriving the address. | |
| const std::uint64_t * | page_ptr {nullptr} |
| As row_ptr, for the two-byte page bitmap. | |
| std::int32_t | hi_class {-1} |
| Class hi_ptr / hi_never were resolved for; -1 while unresolved. | |
| const cp_hi_table * | hi_ptr {nullptr} |
| The resolved sparse hi table for hi_class, or null when it has none usable. | |
| bool | hi_never {false} |
| Set when hi_class has no high ranges at all, so every cp past the page bitmap misses. | |
Reusable VM scratch state.
One run allocates nothing once warm (and never allocates with static containers); find_all-style loops reuse the same state across runs. The two thread lists are flipped by index, never swapped.
| ThreadList | The thread-list type (a basic_thread_list). |
| EpsVec | Container for the epsilon-closure stack. |
|
inlineconstexprnoexcept |
Value-initializes table and cp_page during constant evaluation only.
Same reason as real::detail::static_vec's own constructor: MSVC's constant evaluator rejects an object carrying an indeterminate subobject even where nothing reads it (C2131 on static_regex's compile-time assertions), while clang and gcc accept it. The run-time path, which is the one that was paying a 496-byte clear per search(), keeps the trivial initialization everywhere.
| std::int32_t real::detail::basic_pike_state< ThreadList, EpsVec >::cp_page_class {-1} |
Membership bitmap for a cp_class over the 2-byte UTF-8 range [U+0080, U+07FF], and the class it was built for. European text lives almost entirely in this range (Latin, IPA, Greek, Cyrillic, Hebrew, Arabic…), so a 240-byte bitmap answers it in one load. Built once per class and reused across a find_all-style walk.
Code points beyond U+07FF (CJK, astral) use cp_hi_table (2-stage sparse pages), not an inline BMP array — expanding this field would inflate every pattern's hot state (ASCII class-loop sensitivity, §A 7.46). The table is heap-only (thread-local cache) and built lazily on the first high-cp membership probe.
| std::int32_t real::detail::basic_pike_state< ThreadList, EpsVec >::table_class {-1} |
Flat 256-byte membership table for the hot single-class scan, and the class index it was built for (-1 = none).
The class-scanning fast paths ([…]+, ./negated-class) test one class for every byte. A flat byte-indexed table answers membership with a single load, versus the bitmap's shift-and-mask (measured ~2x faster in a tight scan — the byte-classification technique used by DFA/JIT engines). It is built once and reused across a find_all-style walk (the state is shared), so it adds nothing to the program or to the static binary.