REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
Loading...
Searching...
No Matches
real.hpp
Go to the documentation of this file.
1
7#ifndef REAL_REAL_HPP
8#define REAL_REAL_HPP
9
10#include "real/version.hpp"
11
12#include <iterator>
13#include <optional>
14#include <span>
15#include <string>
16#include <string_view>
17#include <utility>
18#include <vector>
19
20#include "real/engine/pike.hpp"
21#include "real/core/program.hpp"
22#include "real/storage.hpp"
23#include "real/unicode/utf8.hpp"
24
25namespace real {
26
38 template <typename SlotStorage>
40 {
41 public:
42
46 constexpr basic_match_result() = default;
47
56 constexpr basic_match_result(std::string_view text,
57 SlotStorage slots,
58 bool matched,
59 std::string_view pattern,
60 std::span<const detail::named_group> names)
61 : text_(text),
62 slots_(std::move(slots)),
64 pattern_(pattern),
65 names_(names)
66 {}
67
89 template <bool Cascade, typename Vm>
90 constexpr bool engine_refill(Vm& vm,
91 std::string_view text,
92 std::size_t pos,
94 std::size_t forbid,
95 std::string_view pattern,
96 std::span<const detail::named_group> names)
97 {
98 const bool ok {vm.template run<Cascade>(text, pos, mode, slots_, forbid)};
99 text_ = text;
100 matched_ = ok;
101 pattern_ = pattern;
102 names_ = names;
103 return ok;
104 }
105
108 constexpr void bind_context(std::string_view text,
109 std::string_view pattern,
110 std::span<const detail::named_group> names)
111 {
112 text_ = text;
113 pattern_ = pattern;
114 names_ = names;
115 }
116
119 template <bool Cascade, typename Vm>
120 constexpr bool engine_refill_hot(Vm& vm,
121 std::string_view text,
122 std::size_t pos,
123 detail::run_mode mode,
124 std::size_t forbid,
126 {
127 matched_ = vm.template run<Cascade>(text, pos, mode, slots_, forbid, sem);
128 return matched_;
129 }
130
134 [[nodiscard]] constexpr bool matched() const
135 {
136 return matched_;
137 }
138
142 constexpr explicit operator bool() const {
143 return matched_;
144 }
145
149 [[nodiscard]] constexpr std::size_t size() const
150 {
151 return slots_.size() / 2;
152 }
153
159 [[nodiscard]] constexpr std::size_t start(std::size_t group = 0) const
160 {
161 return matched_ && group < size() ? slots_[2 * group] : npos;
162 }
163
169 [[nodiscard]] constexpr std::size_t end(std::size_t group = 0) const
170 {
171 return matched_ && group < size() ? slots_[(2 * group) + 1] : npos;
172 }
173
179 [[nodiscard]] constexpr std::string_view operator[](std::size_t group) const
180 {
181 const std::size_t s {start(group)};
182 return s == npos ? std::string_view {} : text_.substr(s, end(group) - s);
183 }
184
190 [[nodiscard]] constexpr std::size_t group_index(std::string_view name) const
191 {
192 for (const detail::named_group& named_group : names_) {
193 const auto begin {static_cast<std::size_t>(named_group.begin)};
194 const auto length {static_cast<std::size_t>(named_group.end - named_group.begin)};
195 if (pattern_.substr(begin, length) == name) {
196 return static_cast<std::size_t>(named_group.group);
197 }
198 }
199 return npos;
200 }
201
207 [[nodiscard]] constexpr std::size_t start(std::string_view name) const
208 {
209 const std::size_t g {group_index(name)};
210 return g == npos ? npos : start(g);
211 }
212
218 [[nodiscard]] constexpr std::size_t end(std::string_view name) const
219 {
220 const std::size_t g {group_index(name)};
221 return g == npos ? npos : end(g);
222 }
223
229 [[nodiscard]] constexpr std::string_view operator[](std::string_view name) const
230 {
231 const std::size_t g {group_index(name)};
232 return g == npos ? std::string_view {} : (*this)[g];
233 }
234
235 private:
236
237 std::string_view text_;
238 SlotStorage slots_;
239 bool matched_ {};
240 std::string_view pattern_;
241 std::span<const detail::named_group> names_;
242 };
243
248
258 template <typename Storage>
260 {
261 public:
262
264 using difference_type = std::ptrdiff_t;
265 using reference = const value_type&;
266 using pointer = const value_type*;
267 using iterator_category = std::forward_iterator_tag;
268
272 constexpr basic_match_iterator() = default;
273
283 std::string_view pattern,
284 std::string_view text,
285 std::size_t start = 0,
287 : prog_(prog),
288 pattern_(pattern),
289 text_(text),
290 pos_(start),
291 done_(false),
292 // decided ONCE per walk, never per match. Longest forces the non-cascade variant: like every other
293 // fast path, the memchr-cascade class-run is guarded to first mode (the PROTO-kLongest lesson), so a
294 // longest walk must run the general loop.
295 cascade_(sem == match_semantics::first && prog.hints.stop_set_size >= 1),
296 sem_(sem)
297 {
298 current_.bind_context(text_, pattern_, prog_.names); // invariant across the walk — set once, not per match
299 advance();
300 }
301
305 [[nodiscard]] constexpr const value_type& operator*() const
306 {
307 return current_;
308 }
309
313 [[nodiscard]] constexpr const value_type* operator->() const
314 {
315 return &current_;
316 }
317
323 {
324 advance();
325 return *this;
326 }
327
333 {
334 basic_match_iterator previous {*this};
335 advance();
336 return previous;
337 }
338
344 [[nodiscard]] constexpr bool operator==(const basic_match_iterator& other) const
345 {
346 return done_ == other.done_ && (done_ || pos_ == other.pos_);
347 }
348
349 private:
350
352 std::string_view pattern_;
353 std::string_view text_;
354 std::size_t pos_ {};
355 std::size_t forbid_empty_until_ {};
356 bool done_ {true};
357 bool cascade_ {};
360 typename Storage::state_type state_;
361
365 constexpr void advance()
366 {
367 if (done_ || pos_ > text_.size()) {
368 done_ = true;
369 return;
370 }
372 // Refresh the one held result in place, reusing its slot buffer (no per-match allocation). The
373 // Cascade choice is the iterator's compile-time-dispatched cascade_, fixed once at construction, so
374 // the common (non-cascade) walk runs the pre-OPT-C hot path unchanged.
375 const bool ok {cascade_
376 ? current_.template engine_refill_hot<true>(vm, text_, pos_, detail::run_mode::search,
378 : current_.template engine_refill_hot<false>(vm, text_, pos_, detail::run_mode::search,
380 if (!ok) {
381 done_ = true;
382 return;
383 }
384 const std::size_t start {current_.start(0)};
385 const std::size_t end {current_.end(0)};
386 pos_ = end;
387 if (end == start) {
388 // CPython 3.7+: after an empty match, the next match may start at the
389 // same position only if it is non-empty; another empty match there is
390 // skipped. Forbid empty matches up to the next character boundary (a
391 // codepoint, or one raw byte in binary mode) so the skip stays aligned.
392 forbid_empty_until_ = end >= text_.size()
393 ? text_.size() + 1
394 : end + (prog_.byte_mode ? 1 : detail::codepoint_advance(text_, end));
395 }
396 else {
397 forbid_empty_until_ = 0; // non-empty match: no restriction next time
398 }
399 }
400 };
401
406 template <typename Storage>
408 {
409 public:
410
420 std::string_view pattern,
421 std::string_view text,
422 std::size_t start = 0,
424 : prog_(prog),
425 pattern_(pattern),
426 text_(text),
427 start_(start),
428 sem_(sem)
429 {}
430
434 [[nodiscard]] constexpr basic_match_iterator<Storage> begin() const
435 {
436 return {prog_, pattern_, text_, start_, sem_};
437 }
438
442 [[nodiscard]] constexpr basic_match_iterator<Storage> end() const
443 {
444 return {};
445 }
446
447 private:
448
450 std::string_view pattern_;
451 std::string_view text_;
452 std::size_t start_ {};
454 };
455
466 template <typename Storage>
468 {
469 public:
470
472
479 constexpr explicit basic_regex(std::string_view pattern,
481 requires(!Storage::is_compile_time)
482 : program_(Storage::compile(pattern, compile_flags))
483 {}
484
488 constexpr basic_regex()
489 requires(Storage::is_compile_time)
490 = default;
491
497 [[nodiscard]] constexpr result_type match(std::string_view text) const
498 {
499 return run(text, detail::run_mode::prefix);
500 }
501
507 [[nodiscard]] constexpr result_type fullmatch(std::string_view text) const
508 {
509 return run(text, detail::run_mode::full);
510 }
511
517 [[nodiscard]] constexpr result_type search(std::string_view text) const
518 {
519 return run(text, detail::run_mode::search);
520 }
521
527 [[nodiscard]] constexpr result_type match(std::string_view text,
528 std::size_t pos,
529 std::size_t endpos = npos) const
530 {
531 return run(text, pos, endpos, detail::run_mode::prefix);
532 }
533
537 [[nodiscard]] constexpr result_type fullmatch(std::string_view text,
538 std::size_t pos,
539 std::size_t endpos = npos) const
540 {
541 return run(text, pos, endpos, detail::run_mode::full);
542 }
543
547 [[nodiscard]] constexpr result_type search(std::string_view text,
548 std::size_t pos,
549 std::size_t endpos = npos) const
550 {
551 return run(text, pos, endpos, detail::run_mode::search);
552 }
553
559 [[nodiscard]] constexpr result_type match(const char* text) const
560 {
561 return match(std::string_view(text));
562 }
563
569 [[nodiscard]] constexpr result_type fullmatch(const char* text) const
570 {
571 return fullmatch(std::string_view(text));
572 }
573
579 [[nodiscard]] constexpr result_type search(const char* text) const
580 {
581 return search(std::string_view(text));
582 }
583
594 [[nodiscard]] constexpr basic_match_range<Storage> find_iter(std::string_view text) const&
595 {
596 return {program_.view(), pattern(), text};
597 }
598
604 [[nodiscard]] constexpr basic_match_range<Storage> find_iter(const char* text) const&
605 {
606 return find_iter(std::string_view(text));
607 }
608
615 [[nodiscard]] constexpr basic_match_range<Storage> find_iter(std::string_view text,
616 std::size_t pos,
617 std::size_t endpos = npos) const&
618 {
619 const std::size_t end {endpos < text.size() ? endpos : text.size()};
620 return {program_.view(), pattern(), text.substr(0, end), pos};
621 }
622
630 [[nodiscard]] constexpr basic_match_range<Storage> find_iter_longest(std::string_view text,
631 std::size_t pos = 0,
632 std::size_t endpos = npos) const&
633 {
634 const std::size_t end {endpos < text.size() ? endpos : text.size()};
635 return {program_.view(), pattern(), text.substr(0, end), pos, match_semantics::longest};
636 }
637
641 [[nodiscard]] basic_match_range<Storage> find_iter_longest(std::string_view, std::size_t,
642 std::size_t) const&& = delete;
643
647 [[nodiscard]] basic_match_range<Storage> find_iter(std::string_view text) const&& = delete;
651 [[nodiscard]] basic_match_range<Storage> find_iter(const char* text) const&& = delete;
655 [[nodiscard]] basic_match_range<Storage> find_iter(std::string_view text, std::size_t,
656 std::size_t = npos) const&& = delete;
657
667 [[nodiscard]] constexpr std::vector<result_type> find_all(std::string_view text) const&
668 {
669 std::vector<result_type> result;
670 for (const result_type& match : find_iter(text)) {
671 result.push_back(match);
672 }
673 return result;
674 }
675
681 [[nodiscard]] constexpr std::vector<result_type> find_all(const char* text) const&
682 {
683 return find_all(std::string_view(text));
684 }
685
689 [[nodiscard]] std::vector<result_type> find_all(std::string_view text) const&& = delete;
693 [[nodiscard]] std::vector<result_type> find_all(const char* text) const&& = delete;
694
708 [[nodiscard]] constexpr std::string replace(std::string_view text,
709 std::string_view replacement,
710 std::size_t max_count = 0) const
711 {
712 std::string result;
713 std::size_t last {};
714 std::size_t done {};
715 for (const result_type& match : find_iter(text)) {
716 if (max_count != 0 && done == max_count) {
717 break;
718 }
719 result.append(text.substr(last, match.start() - last));
720 expand_replacement(result, match, replacement);
721 last = match.end();
722 ++done;
723 }
724 result.append(text.substr(last));
725 return result;
726 }
727
738 [[nodiscard]] constexpr std::vector<std::string_view> split(std::string_view text,
739 std::size_t max_splits = 0) const
740 {
741 std::vector<std::string_view> result;
742 std::size_t last {};
743 std::size_t done {};
744 for (const result_type& match : find_iter(text)) {
745 if (max_splits != 0 && done == max_splits) {
746 break;
747 }
748 result.push_back(text.substr(last, match.start() - last));
749 for (std::size_t group = 1; group < match.size(); ++group) {
750 result.push_back(match[group]);
751 }
752 last = match.end();
753 ++done;
754 }
755 result.push_back(text.substr(last));
756 return result;
757 }
758
765 [[nodiscard]] constexpr std::vector<std::string_view> split(const char* text,
766 std::size_t max_splits = 0) const
767 {
768 return split(std::string_view(text), max_splits);
769 }
770
771 // Searched text must outlive the result: reject temporary std::string.
772 [[nodiscard]] result_type match(const std::string&& text) const = delete;
773 [[nodiscard]] result_type fullmatch(const std::string&& text) const = delete;
774 [[nodiscard]] result_type search(const std::string&& text) const = delete;
775 [[nodiscard]] result_type match(const std::string && text, std::size_t, std::size_t = npos) const = delete;
776 [[nodiscard]] result_type fullmatch(const std::string && text, std::size_t, std::size_t = npos) const = delete;
777 [[nodiscard]] result_type search(const std::string && text, std::size_t, std::size_t = npos) const = delete;
778 [[nodiscard]] basic_match_range<Storage> find_iter(const std::string&& text) const& = delete;
779 [[nodiscard]] basic_match_range<Storage> find_iter(const std::string && text, std::size_t,
780 std::size_t = npos) const& = delete;
781 [[nodiscard]] std::vector<result_type> find_all(const std::string&& text) const& = delete;
782 [[nodiscard]] std::vector<std::string_view> split(const std::string&& text,
783 std::size_t max_splits = 0) const = delete;
784
788 [[nodiscard]] constexpr std::string_view pattern() const
789 {
790 return program_.pattern();
791 }
792
796 [[nodiscard]] constexpr flags compile_flags() const
797 {
798 return program_.compiled_flags();
799 }
800
804 [[nodiscard]] constexpr std::size_t group_count() const
805 {
806 return (program_.view().slot_count / 2) - 1;
807 }
808
817 [[nodiscard]] constexpr detail::program_view raw_program() const
818 {
819 return program_.view();
820 }
821
833 [[nodiscard]] constexpr bool has_first_byte_set() const noexcept
834 {
836 }
837
844 [[nodiscard]] constexpr std::optional<unsigned char> unique_first_byte() const noexcept
845 {
846 const int first {raw_program().hints.single_first};
847 return first < 0 ? std::nullopt : std::optional<unsigned char>(static_cast<unsigned char>(first));
848 }
849
862 [[nodiscard]] constexpr bool may_start_with(unsigned char byte) const noexcept
863 {
864 const detail::program_view view {raw_program()};
865 return !view.hints.first_bytes_valid || view.hints.first_bytes.test(byte);
866 }
867
873 [[nodiscard]] constexpr std::size_t group_index(std::string_view name) const
874 {
875 for (const detail::named_group& named_group : program_.view().names) {
876 if (name_of(named_group) == name) {
877 return static_cast<std::size_t>(named_group.group);
878 }
879 }
880 return npos;
881 }
882
887 [[nodiscard]] constexpr std::vector<std::pair<std::string_view, std::size_t>>
889 {
890 std::vector<std::pair<std::string_view, std::size_t>> result;
891 for (const detail::named_group& named_group : program_.view().names) {
892 result.emplace_back(name_of(named_group), static_cast<std::size_t>(named_group.group));
893 }
894 return result;
895 }
896
897 private:
898
899 Storage program_;
900
906 [[nodiscard]] constexpr std::string_view name_of(const detail::named_group& named_group) const
907 {
908 return pattern().substr(static_cast<std::size_t>(named_group.begin),
909 static_cast<std::size_t>(named_group.end - named_group.begin));
910 }
911
922 constexpr void expand_replacement(std::string& out,
923 const result_type& match,
924 std::string_view replacement) const
925 {
926 std::size_t i {};
927 while (i < replacement.size()) {
928 const char ch {replacement[i]};
929 if (ch != '$') {
930 out.push_back(ch);
931 ++i;
932 continue;
933 }
934 ++i;
935 if (i >= replacement.size()) {
936 throw regex_error("dangling $ in replacement", i - 1);
937 }
938 const char next_ch {replacement[i]};
939 if (next_ch == '$') {
940 out.push_back('$');
941 ++i;
942 }
943 else if (next_ch == '&') {
944 out.append(match[0]);
945 ++i;
946 }
947 else if (next_ch >= '0' && next_ch <= '9') {
948 std::size_t group {};
949 while (i < replacement.size() && replacement[i] >= '0' &&
950 replacement[i] <= '9') {
951 group = (group * 10) + static_cast<std::size_t>(replacement[i] - '0');
952 ++i;
953 }
954 if (group >= match.size()) {
955 throw regex_error("invalid group reference in replacement", i);
956 }
957 out.append(match[group]);
958 }
959 else if (next_ch == '{') {
960 const std::size_t name_begin {i + 1};
961 std::size_t j {name_begin};
962 while (j < replacement.size() && replacement[j] != '}') {
963 ++j;
964 }
965 if (j == replacement.size() || j == name_begin) {
966 throw regex_error("malformed ${name} in replacement", i);
967 }
968 const std::size_t group =
969 match.group_index(replacement.substr(name_begin, j - name_begin));
970 if (group == npos) {
971 throw regex_error("unknown group name in replacement", i);
972 }
973 out.append(match[group]);
974 i = j + 1;
975 }
976 else {
977 throw regex_error("invalid $ escape in replacement", i);
978 }
979 }
980 }
981
988 [[nodiscard]] constexpr result_type run(std::string_view text,
989 detail::run_mode mode) const
990 {
991 return run(text, 0, npos, mode);
992 }
993
1010 [[nodiscard]] constexpr result_type run(std::string_view text,
1011 std::size_t pos,
1012 std::size_t endpos,
1013 detail::run_mode mode,
1015 {
1016 const std::size_t end {endpos < text.size() ? endpos : text.size()};
1017 typename Storage::state_type state;
1018 typename Storage::slot_storage slots;
1019 const detail::program_view prog {program_.view()};
1020 detail::pike_vm vm(prog, state);
1021 // OPT-C Cascade is chosen once here (a single search), never in the per-byte scan.
1022 const bool matched {prog.hints.stop_set_size >= 1
1023 ? vm.template run<true>(text.substr(0, end), pos, mode, slots, 0, sem)
1024 : vm.template run<false>(text.substr(0, end), pos, mode, slots, 0, sem)};
1025 return {text, std::move(slots), matched, pattern(), prog.names};
1026 }
1027
1028 public:
1029
1038 [[nodiscard]] result_type search_longest(std::string_view text) const
1039 {
1041 }
1042
1047 [[nodiscard]] result_type search_longest(std::string_view text,
1048 std::size_t pos,
1049 std::size_t endpos = npos) const
1050 {
1051 return run(text, pos, endpos, detail::run_mode::search, match_semantics::longest);
1052 }
1053 };
1054
1059
1070 template <fixed_string Pattern, flags F = flags::none>
1072} // namespace real
1073
1074#endif // REAL_REAL_HPP
Forward iterator over the non-overlapping matches in a text.
Definition real.hpp:260
std::string_view pattern_
Pattern text (named lookups).
Definition real.hpp:352
value_type current_
The current match.
Definition real.hpp:359
match_semantics sem_
leftmost-first (default) or longest (find_iter_longest).
Definition real.hpp:358
constexpr bool operator==(const basic_match_iterator &other) const
Returns true if both denote the same position/end.
Definition real.hpp:344
std::ptrdiff_t difference_type
Iterator traits.
Definition real.hpp:264
std::string_view text_
The text being scanned.
Definition real.hpp:353
constexpr const value_type & operator*() const
Returns the current match.
Definition real.hpp:305
constexpr basic_match_iterator()=default
Constructs the end sentinel.
std::forward_iterator_tag iterator_category
Multipass: copies are independent.
Definition real.hpp:267
bool done_
True once exhausted.
Definition real.hpp:356
constexpr basic_match_iterator operator++(int)
Advances to the next match (post-increment).
Definition real.hpp:332
constexpr basic_match_iterator & operator++()
Advances to the next match.
Definition real.hpp:322
detail::program_view prog_
The program being run.
Definition real.hpp:351
bool cascade_
OPT-C: chosen once — run the memchr-cascade class-run variant for this whole walk.
Definition real.hpp:357
Storage::state_type state_
VM scratch, reused across the walk.
Definition real.hpp:360
constexpr const value_type * operator->() const
Returns pointer to the current match.
Definition real.hpp:313
constexpr void advance()
Finds the next match, applying the empty-match advance rules.
Definition real.hpp:365
constexpr basic_match_iterator(detail::program_view prog, std::string_view pattern, std::string_view text, std::size_t start=0, match_semantics sem=match_semantics::first)
Constructs a begin iterator and finds the first match.
Definition real.hpp:282
std::size_t pos_
Current scan offset.
Definition real.hpp:354
std::size_t forbid_empty_until_
Empty-match guard (see pike.hpp).
Definition real.hpp:355
A range of matches, returned by find_iter() and usable in range-for.
Definition real.hpp:408
constexpr basic_match_iterator< Storage > begin() const
Returns an iterator to the first match.
Definition real.hpp:434
std::string_view text_
The text to iterate.
Definition real.hpp:451
std::string_view pattern_
Pattern text (named lookups).
Definition real.hpp:450
constexpr basic_match_iterator< Storage > end() const
Returns the end sentinel.
Definition real.hpp:442
detail::program_view prog_
The program being run.
Definition real.hpp:449
constexpr basic_match_range(detail::program_view prog, std::string_view pattern, std::string_view text, std::size_t start=0, match_semantics sem=match_semantics::first)
Binds the range to a program and text.
Definition real.hpp:419
std::size_t start_
Byte offset to begin iterating from (region support).
Definition real.hpp:452
match_semantics sem_
leftmost-first (default) or longest.
Definition real.hpp:453
The result of a match attempt: success, spans and captures.
Definition real.hpp:40
constexpr std::size_t end(std::string_view name) const
Returns its end offset, or npos if unknown.
Definition real.hpp:218
constexpr std::string_view operator[](std::size_t group) const
View of a group's matched text.
Definition real.hpp:179
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 reco...
Definition real.hpp:120
constexpr std::size_t start(std::string_view name) const
Returns its start offset, or npos if unknown.
Definition real.hpp:207
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).
Definition real.hpp:56
std::string_view text_
The searched text.
Definition real.hpp:237
SlotStorage slots_
Flattened capture slots.
Definition real.hpp:238
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....
Definition real.hpp:90
constexpr std::string_view operator[](std::string_view name) const
Returns its matched text, empty if unknown/unset.
Definition real.hpp:229
constexpr std::size_t start(std::size_t group=0) const
Start byte offset of a group.
Definition real.hpp:159
constexpr std::size_t end(std::size_t group=0) const
End byte offset (exclusive) of a group.
Definition real.hpp:169
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 s...
Definition real.hpp:108
constexpr basic_match_result()=default
Constructs an empty (non-matched) result.
bool matched_
Whether a match occurred.
Definition real.hpp:239
std::span< const detail::named_group > names_
Borrowed named-group table.
Definition real.hpp:241
std::string_view pattern_
Pattern text (for named lookups).
Definition real.hpp:240
constexpr std::size_t group_index(std::string_view name) const
Resolves a group name to its number.
Definition real.hpp:190
constexpr bool matched() const
Returns true if the attempt matched.
Definition real.hpp:134
constexpr std::size_t size() const
Returns the number of groups, including group 0 (the whole match).
Definition real.hpp:149
A compiled regular expression, parameterized on its storage policy.
Definition real.hpp:468
constexpr std::string_view name_of(const detail::named_group &named_group) const
Returns its name, sliced from the pattern text.
Definition real.hpp:906
result_type search(const std::string &&text, std::size_t, std::size_t=npos) const =delete
Deleted: temporary text would dangle.
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).
Definition real.hpp:738
constexpr result_type search(std::string_view text) const
Leftmost match anywhere in text (Python re.search).
Definition real.hpp:517
constexpr basic_regex(std::string_view pattern, flags compile_flags=flags::none)
Compiles pattern at run time (the real::regex constructor).
Definition real.hpp:479
Storage program_
The storage policy holding the compiled program.
Definition real.hpp:899
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)....
Definition real.hpp:1047
constexpr detail::program_view raw_program() const
The raw compiled program, for embedders (advanced).
Definition real.hpp:817
constexpr std::size_t group_count() const
Returns the number of capturing groups (excluding group 0).
Definition real.hpp:804
result_type match(const std::string &&text, std::size_t, std::size_t=npos) const =delete
Deleted: temporary text would dangle.
constexpr std::size_t group_index(std::string_view name) const
Resolves a group name to its number.
Definition real.hpp:873
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.
constexpr void expand_replacement(std::string &out, const result_type &match, std::string_view replacement) const
Appends replacement to out, substituting group references.
Definition real.hpp:922
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 rat...
Definition real.hpp:630
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.
Definition real.hpp:1010
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)....
Definition real.hpp:615
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)....
Definition real.hpp:527
constexpr std::vector< result_type > find_all(std::string_view text) const &
All matches, eagerly (like Python re.findall but full results).
Definition real.hpp:667
constexpr bool has_first_byte_set() const noexcept
Whether first-byte filtering is useful for this pattern.
Definition real.hpp:833
result_type fullmatch(const std::string &&text, std::size_t, std::size_t=npos) const =delete
Deleted: temporary text would dangle.
constexpr bool may_start_with(unsigned char byte) const noexcept
Whether a non-empty match can begin with byte (sound, conservative).
Definition real.hpp:862
constexpr std::vector< std::pair< std::string_view, std::size_t > > named_groups() const
All named groups as (name, number) pairs, in declaration order.
Definition real.hpp:888
std::vector< std::string_view > split(const std::string &&text, std::size_t max_splits=0) const =delete
Deleted: temporary text would dangle.
basic_match_range< Storage > find_iter(const char *text) const &&=delete
Deleted: find_iter on a temporary regex would dangle.
constexpr result_type match(const char *text) const
match overload for string literals.
Definition real.hpp:559
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).
Definition real.hpp:988
constexpr result_type search(const char *text) const
search overload for string literals.
Definition real.hpp:579
basic_match_range< Storage > find_iter(std::string_view text) const &&=delete
Deleted: find_iter on a temporary regex would dangle.
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).
Definition real.hpp:547
basic_match_range< Storage > find_iter(const std::string &&text, std::size_t, std::size_t=npos) const &=delete
Deleted: temporary text would dangle.
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.
Definition real.hpp:537
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::string_view pattern() const
Returns the pattern text this regex was compiled from.
Definition real.hpp:788
constexpr flags compile_flags() const
Returns the effective flags (constructor flags merged with a (?ims) prefix).
Definition real.hpp:796
constexpr result_type match(std::string_view text) const
Match anchored at the start of text (Python re.match).
Definition real.hpp:497
result_type search_longest(std::string_view text) const
EXPERIMENTAL, opt-in: a single leftmost-**longest** search (POSIX / RE2 set_longest_match),...
Definition real.hpp:1038
constexpr std::vector< result_type > find_all(const char *text) const &
find_all overload for string literals.
Definition real.hpp:681
constexpr result_type fullmatch(std::string_view text) const
Match the entire text (Python re.fullmatch).
Definition real.hpp:507
constexpr basic_regex()=default
Default constructor for the stateless compile-time storage (static_regex).
constexpr result_type fullmatch(const char *text) const
fullmatch overload for string literals.
Definition real.hpp:569
constexpr std::string replace(std::string_view text, std::string_view replacement, std::size_t max_count=0) const
Replaces matches in text (Python re.sub).
Definition real.hpp:708
std::vector< result_type > find_all(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 match(const std::string &&text) const =delete
Deleted: temporary text would dangle.
constexpr basic_match_range< Storage > find_iter(std::string_view text) const &
Lazy range over all non-overlapping matches (Python re.finditer).
Definition real.hpp:594
constexpr std::vector< std::string_view > split(const char *text, std::size_t max_splits=0) const
split overload for string literals.
Definition real.hpp:765
constexpr std::optional< unsigned char > unique_first_byte() const noexcept
The single byte every non-empty match must begin with, if unique.
Definition real.hpp:844
constexpr basic_match_range< Storage > find_iter(const char *text) const &
find_iter overload for string literals.
Definition real.hpp:604
std::vector< result_type > find_all(const char *text) const &&=delete
Deleted: find_all on a temporary regex would dangle.
basic_match_range< Storage > find_iter(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.
std::vector< result_type > find_all(std::string_view text) const &&=delete
Deleted: find_all on a temporary regex would dangle.
The Pike VM, generic over the scratch-state container policy.
Definition pike.hpp:306
constexpr std::size_t codepoint_advance(std::string_view text, std::size_t pos)
Number of bytes from pos to the next code-point boundary, for advancing past an empty match during it...
Definition utf8.hpp:108
run_mode
How a VM run is anchored.
Definition pike.hpp:47
@ search
First match anywhere (Python re.search).
@ prefix
Anchored at the start position (Python re.match).
@ full
Anchored at both ends (Python re.fullmatch).
constexpr std::size_t npos
Sentinel for "no position" / unset capture slot (akin to std::string::npos).
Definition program.hpp:33
match_semantics
Which match a search returns among those starting at the leftmost position (an experimental,...
Definition program.hpp:57
@ longest
Leftmost-longest (POSIX / RE2 set_longest_match): the longest overall match wins the bounds.
@ first
Leftmost-first (Perl / Python re / the crate): source-order thread priority decides....
flags
Compilation flags, mirroring Python's re.I, re.M and re.S.
Definition program.hpp:42
@ none
No flags.
The Pike VM — a Thompson NFA simulation — and its fast paths.
Compiled form of a pattern and the public flags / error types.
Storage policies: where a program lives and how scratch is allocated.
A named capture group.
Definition program.hpp:329
std::int32_t begin
Start offset of the name in the pattern text.
Definition program.hpp:331
std::int32_t end
End offset (exclusive) of the name.
Definition program.hpp:332
bool first_bytes_valid
False when an empty match is possible.
Definition program.hpp:272
std::int16_t single_first
The unique possible first byte, or -1.
Definition program.hpp:274
bool byte_mode
flags::bytes mode — positions are raw bytes.
Definition program.hpp:358
std::span< const named_group > names
Named capture groups.
Definition program.hpp:349
pattern_hints hints
Search-acceleration hints.
Definition program.hpp:360
UTF-8 position arithmetic for match iteration.
REAL's version macros and the C++20 language-standard guard.