REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
Loading...
Searching...
No Matches
regex_match.hpp
Go to the documentation of this file.
1
7#ifndef REAL_STD_REGEX_MATCH_HPP
8#define REAL_STD_REGEX_MATCH_HPP
9
10// Internal — do not include directly.
11// Users: #include <real/real.hpp> (or the documented opt-ins <real/dfa.hpp>, <real/std/regex.hpp>).
12
13#include "regex_core.hpp"
14
15#include <algorithm>
16#include <iterator>
17
18namespace real::compat {
28 template <typename BidirIt>
30 {
31 static_assert(std::contiguous_iterator<BidirIt>,
32 "real::compat::sub_match requires a contiguous iterator");
33
34 public:
35
36 using iterator = BidirIt;
37 using value_type = typename std::iterator_traits<BidirIt>::value_type;
38 using difference_type = typename std::iterator_traits<BidirIt>::difference_type;
39 using string_type = std::basic_string<value_type>;
40
41 BidirIt first {};
42 BidirIt second {};
43 bool matched {false};
44
46 [[nodiscard]] difference_type length() const
47 {
48 return matched ? std::distance(first, second) : difference_type {0};
49 }
50
52 [[nodiscard]] string_type str() const
53 {
55 }
56
58 operator string_type() const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
59 {
60 return str();
61 }
62
64 [[nodiscard]] std::basic_string_view<value_type> view() const
65 {
66 return matched ? std::basic_string_view<value_type>(std::to_address(first),
67 static_cast<std::size_t>(length()))
68 : std::basic_string_view<value_type> {};
69 }
70
72 [[nodiscard]] int compare(const string_type& other) const
73 {
74 return str().compare(other);
75 }
76
77 [[nodiscard]] int compare(const sub_match& other) const
78 {
79 return str().compare(other.str());
80 }
81 };
82
84 template <typename BidirIt>
86 const typename sub_match<BidirIt>::string_type& rhs)
87 {
88 return lhs.str() == rhs;
89 }
90
91 template <typename BidirIt>
93 const sub_match<BidirIt>& rhs)
94 {
95 return lhs == rhs.str();
96 }
97
98 template <typename BidirIt>
100 const sub_match<BidirIt>& rhs)
101 {
102 return lhs.str() == rhs.str();
103 }
104
115 template <typename BidirIt, typename Alloc = std::allocator<sub_match<BidirIt>>>
117 {
118 public:
119
123 using const_iterator = typename std::vector<value_type, Alloc>::const_iterator;
125 using difference_type = typename std::iterator_traits<BidirIt>::difference_type;
126 using size_type = std::size_t;
127 using char_type = typename std::iterator_traits<BidirIt>::value_type;
128 using string_type = std::basic_string<char_type>;
129
131 [[nodiscard]] bool ready() const noexcept
132 {
133 return ready_;
134 }
135
137 [[nodiscard]] size_type size() const noexcept
138 {
139 return groups_.size();
140 }
141
142 [[nodiscard]] bool empty() const noexcept
143 {
144 return groups_.empty();
145 }
146
152 {
153 return n < groups_.size() ? groups_[n] : unmatched_;
154 }
155
158 [[nodiscard]] difference_type position(size_type n = 0) const
159 {
160 return n < groups_.size() ? std::distance(first_, groups_[n].first)
161 : std::distance(first_, last_);
162 }
163
165 [[nodiscard]] difference_type length(size_type n = 0) const
166 {
167 return n < groups_.size() ? groups_[n].length() : difference_type {0};
168 }
169
171 [[nodiscard]] string_type str(size_type n = 0) const
172 {
173 return (*this)[n].str();
174 }
175
177 [[nodiscard]] const value_type& prefix() const
178 {
179 return prefix_;
180 }
181
183 [[nodiscard]] const value_type& suffix() const
184 {
185 return suffix_;
186 }
187
188 [[nodiscard]] const_iterator begin() const
189 {
190 return groups_.begin();
191 }
192
193 [[nodiscard]] const_iterator end() const
194 {
195 return groups_.end();
196 }
197
198 [[nodiscard]] const_iterator cbegin() const
199 {
200 return groups_.begin();
201 }
202
203 [[nodiscard]] const_iterator cend() const
204 {
205 return groups_.end();
206 }
207
208 // --- engine-facing fill helpers (used by the free functions) ---------------------------
209
211 void reset(BidirIt first,
212 BidirIt last)
213 {
214 first_ = first;
215 last_ = last;
216 groups_.clear();
217 prefix_ = suffix_ = value_type {.first = last, .second = last, .matched = false};
218 unmatched_ = value_type {.first = last, .second = last, .matched = false};
219 ready_ = false;
220 }
221
225 {
226 groups_.clear();
227 ready_ = true;
228 }
229
233 void rebase_prefix(BidirIt first)
234 {
237 }
238
242 template <typename RealMatch>
243 void fill_from_real(const RealMatch& match)
244 {
245 groups_.clear();
246 const std::size_t count {match.size()};
247 groups_.reserve(count);
248 for (std::size_t g = 0; g < count; ++g) {
249 const std::size_t start {match.start(g)};
250 const std::size_t fin {match.end(g)};
251 if (start == real::npos || fin == real::npos) {
252 groups_.push_back(value_type {.first = last_, .second = last_, .matched = false});
253 }
254 else {
255 groups_.push_back(value_type {.first = first_ + static_cast<difference_type>(start),
256 .second = first_ + static_cast<difference_type>(fin),
257 .matched = true});
258 }
259 }
260 const std::size_t whole_start {match.start(0)};
261 const std::size_t whole_end {match.end(0)};
263 .second = first_ + static_cast<difference_type>(whole_start),
264 .matched = whole_start > 0};
265 suffix_ = value_type {.first = first_ + static_cast<difference_type>(whole_end),
266 .second = last_,
267 .matched = (first_ + static_cast<difference_type>(whole_end)) != last_};
268 ready_ = true;
269 }
270
272 template <typename StdMatch>
273 void fill_from_std(const StdMatch& match)
274 {
275 groups_.clear();
276 groups_.reserve(match.size());
277 for (const auto& sub : match) {
278 groups_.push_back(value_type {.first = sub.first, .second = sub.second, .matched = sub.matched});
279 }
280 const auto& pre {match.prefix()};
281 const auto& suf {match.suffix()};
282 prefix_ = value_type {.first = pre.first, .second = pre.second, .matched = pre.matched};
283 suffix_ = value_type {.first = suf.first, .second = suf.second, .matched = suf.matched};
284 ready_ = true;
285 }
286
287 private:
288
289 BidirIt first_ {};
290 BidirIt last_ {};
291 std::vector<value_type, Alloc> groups_;
295 bool ready_ {false};
296 };
297
302
307
308 // --- free functions ----------------------------------------------------------------------
309
310 namespace detail {
311
320 [[nodiscard]] inline bool real_honors(regex_constants::match_flag_type mf) noexcept
321 {
322 constexpr unsigned non_constraining {static_cast<unsigned>(regex_constants::match_default)
323 | static_cast<unsigned>(regex_constants::match_any)};
324 return (static_cast<unsigned>(mf) & ~non_constraining) == 0U;
325 }
326
332 [[nodiscard]] inline bool replace_stays_real(regex_constants::match_flag_type f) noexcept
333 {
334 using namespace regex_constants;
335 constexpr unsigned honored {static_cast<unsigned>(match_default) | static_cast<unsigned>(match_any)
336 | static_cast<unsigned>(format_first_only)
337 | static_cast<unsigned>(format_no_copy)};
338 return (static_cast<unsigned>(f) & ~honored) == 0U;
339 }
340
346 [[nodiscard]] inline std::regex_constants::match_flag_type
348 {
349 namespace sc = std::regex_constants;
350 using namespace regex_constants;
351 auto s {sc::match_default};
352 if ((f & match_not_bol) != 0U) { s |= sc::match_not_bol; }
353 if ((f & match_not_eol) != 0U) { s |= sc::match_not_eol; }
354 if ((f & match_not_bow) != 0U) { s |= sc::match_not_bow; }
355 if ((f & match_not_eow) != 0U) { s |= sc::match_not_eow; }
356 if ((f & match_any) != 0U) { s |= sc::match_any; }
357 if ((f & match_not_null) != 0U) { s |= sc::match_not_null; }
358 if ((f & match_continuous) != 0U) { s |= sc::match_continuous; }
359 if ((f & match_prev_avail) != 0U) { s |= sc::match_prev_avail; }
360 if ((f & format_sed) != 0U) { s |= sc::format_sed; }
361 if ((f & format_no_copy) != 0U) { s |= sc::format_no_copy; }
362 if ((f & format_first_only) != 0U) { s |= sc::format_first_only; }
363 return s;
364 }
365
369 template <typename BidirIt, typename CharT, typename Traits>
370 bool run(BidirIt first,
371 BidirIt last,
374 bool anchored,
376 {
377 m.reset(first, last);
378 if constexpr (real_eligible<CharT, Traits>) {
379 if (re.uses_real() && real_honors(mf)) {
380 const std::string_view sv {std::to_address(first),
381 static_cast<std::size_t>(std::distance(first, last))};
382 const real::regex& engine {std::get<real::regex>(re.engine())};
383 // POSIX ERE routes an unanchored search to leftmost-LONGEST bounds (re.posix_longest()); a whole-
384 // sequence match (fullmatch) has one candidate, so longest == first there.
385 const auto result {anchored ? engine.fullmatch(sv)
386 : (re.posix_longest() ? engine.search_longest(sv) : engine.search(sv))};
387 if (!result.matched()) {
388 m.set_ready_no_match(); // std leaves ready()==true, size()==0 on a failed match
389 return false;
390 }
391 m.fill_from_real(result);
392 return true;
393 }
394 }
395 const std::basic_regex<CharT, Traits>& std_engine {re.std_engine()}; // lazy-built if real-backed
396 std::match_results<BidirIt> std_m;
397 const auto sf {to_std_match(mf)};
398 const bool ok {anchored ? std::regex_match(first, last, std_m, std_engine, sf)
399 : std::regex_search(first, last, std_m, std_engine, sf)};
400 if (!ok) {
402 return false;
403 }
404 m.fill_from_std(std_m);
405 return true;
406 }
407
409 template <typename BidirIt, typename CharT, typename Traits>
410 bool run_nocapture(BidirIt first,
411 BidirIt last,
413 bool anchored,
415 {
416 if constexpr (real_eligible<CharT, Traits>) {
417 if (re.uses_real() && real_honors(mf)) {
418 const std::string_view sv {std::to_address(first),
419 static_cast<std::size_t>(std::distance(first, last))};
420 const real::regex& engine {std::get<real::regex>(re.engine())};
421 return anchored ? engine.fullmatch(sv).matched()
422 : (re.posix_longest() ? engine.search_longest(sv) : engine.search(sv)).matched();
423 }
424 }
425 const std::basic_regex<CharT, Traits>& std_engine {re.std_engine()};
426 const auto sf {to_std_match(mf)};
427 return anchored ? std::regex_match(first, last, std_engine, sf)
428 : std::regex_search(first, last, std_engine, sf);
429 }
430 } // namespace detail
431
433 template <typename BidirIt, typename CharT, typename Traits>
434 bool regex_search(BidirIt first,
435 BidirIt last,
439 {
440 return detail::run(first, last, m, re, /*anchored=*/ false, flags);
441 }
442
443 template <typename CharT, typename Traits>
444 bool regex_search(const std::basic_string<CharT>& s,
445 match_results<typename std::basic_string<CharT>::const_iterator>& m,
448 {
449 return detail::run(s.begin(), s.end(), m, re, false, flags);
450 }
451
452 template <typename CharT, typename Traits>
453 bool regex_search(const CharT * s,
457 {
458 return detail::run(s, s + std::char_traits<CharT>::length(s), m, re, false, flags);
459 }
460
461 template <typename BidirIt, typename CharT, typename Traits>
462 bool regex_search(BidirIt first,
463 BidirIt last,
466 {
467 return detail::run_nocapture(first, last, re, false, flags);
468 }
469
470 template <typename CharT, typename Traits>
471 bool regex_search(const std::basic_string<CharT>& s,
474 {
475 return detail::run_nocapture(s.begin(), s.end(), re, false, flags);
476 }
477
478 template <typename CharT, typename Traits>
479 bool regex_search(const CharT * s,
482 {
483 return detail::run_nocapture(s, s + std::char_traits<CharT>::length(s), re, false, flags);
484 }
485
487 template <typename BidirIt, typename CharT, typename Traits>
488 bool regex_match(BidirIt first,
489 BidirIt last,
493 {
494 return detail::run(first, last, m, re, /*anchored=*/ true, flags);
495 }
496
497 template <typename CharT, typename Traits>
498 bool regex_match(const std::basic_string<CharT>& s,
499 match_results<typename std::basic_string<CharT>::const_iterator>& m,
502 {
503 return detail::run(s.begin(), s.end(), m, re, true, flags);
504 }
505
506 template <typename CharT, typename Traits>
507 bool regex_match(const CharT * s,
511 {
512 return detail::run(s, s + std::char_traits<CharT>::length(s), m, re, true, flags);
513 }
514
515 template <typename BidirIt, typename CharT, typename Traits>
516 bool regex_match(BidirIt first,
517 BidirIt last,
520 {
521 return detail::run_nocapture(first, last, re, true, flags);
522 }
523
524 template <typename CharT, typename Traits>
525 bool regex_match(const std::basic_string<CharT>& s,
528 {
529 return detail::run_nocapture(s.begin(), s.end(), re, true, flags);
530 }
531
532 template <typename CharT, typename Traits>
533 bool regex_match(const CharT * s,
536 {
537 return detail::run_nocapture(s, s + std::char_traits<CharT>::length(s), re, true, flags);
538 }
539
540 // Reject matching against an rvalue string (the result would dangle), mirroring real/std. Both the
541 // 3-arg and the 4-arg (with match flags) forms must be deleted — otherwise the temporary binds to
542 // the const-ref overload and the filled match_results dangles into freed storage.
543 template <typename CharT, typename Traits>
544 bool regex_search(const std::basic_string<CharT>&&,
545 match_results<typename std::basic_string<CharT>::const_iterator>&,
546 const basic_regex<CharT, Traits>&) = delete;
547 template <typename CharT, typename Traits>
548 bool regex_search(const std::basic_string<CharT>&&,
549 match_results<typename std::basic_string<CharT>::const_iterator>&,
552 template <typename CharT, typename Traits>
553 bool regex_match(const std::basic_string<CharT>&&,
554 match_results<typename std::basic_string<CharT>::const_iterator>&,
555 const basic_regex<CharT, Traits>&) = delete;
556 template <typename CharT, typename Traits>
557 bool regex_match(const std::basic_string<CharT>&&,
558 match_results<typename std::basic_string<CharT>::const_iterator>&,
561
562 // --- regex_replace -----------------------------------------------------------------------
563
564 namespace detail {
565
574 template <typename RealMatch>
575 void expand_format(std::string& out,
576 const RealMatch& m,
577 std::string_view fmt,
578 std::string_view text,
579 std::size_t prefix_start)
580 {
581 const std::size_t group_count {m.size()}; // includes group 0
582 const std::size_t whole_start {m.start(0)};
583 const std::size_t whole_end {m.end(0)};
584 for (std::size_t i = 0; i < fmt.size(); ++i) {
585 if (fmt[i] != '$') {
586 out.push_back(fmt[i]);
587 continue;
588 }
589 if (i + 1 >= fmt.size()) {
590 out.push_back('$');
591 break;
592 }
593 const char next {fmt[i + 1]};
594 if (next == '$') {
595 out.push_back('$');
596 ++i;
597 }
598 else if (next == '&') {
599 out.append(text.substr(whole_start, whole_end - whole_start));
600 ++i;
601 }
602 else if (next == '`') {
603 out.append(text.substr(prefix_start, whole_start - prefix_start));
604 ++i;
605 }
606 else if (next == '\'') {
607 out.append(text.substr(whole_end));
608 ++i;
609 }
610 else if (next >= '0' && next <= '9') {
611 // ECMAScript / std: greedily take a second digit when present (`$12` -> group 12; `$015`
612 // -> group 01 == 1, then a literal '5'). The 2-digit value is used as-is; a reference to a
613 // group that does not exist expands to nothing (the digits are still consumed). ($0… is
614 // screened to std up front, so `next` here is 1-9.)
615 std::size_t group {static_cast<std::size_t>(next - '0')};
616 std::size_t consumed {1};
617 if (i + 2 < fmt.size() && fmt[i + 2] >= '0' && fmt[i + 2] <= '9') {
618 group = (group * 10) + static_cast<std::size_t>(fmt[i + 2] - '0');
619 consumed = 2;
620 }
621 if (group >= 1 && group < group_count && m.start(group) != real::npos) {
622 out.append(text.substr(m.start(group), m.end(group) - m.start(group)));
623 }
624 i += consumed;
625 }
626 else {
627 out.push_back('$'); // a `$` not forming a valid reference is literal
628 }
629 }
630 }
631 } // namespace detail
632
640 template <typename CharT, typename Traits>
641 std::basic_string<CharT> regex_replace(const std::basic_string<CharT>& s,
643 const std::basic_string<CharT>& fmt,
645 {
646 if constexpr (!detail::real_eligible<CharT, Traits>) {
647 // wide / custom-traits: always std (real is not eligible for this CharT).
648 return std::regex_replace(s, re.std_engine(), fmt, detail::to_std_match(flags));
649 }
650 else {
651 // Route to std when: the pattern is not real-traversable (std/nullable), OR a flag the real
652 // expander cannot honor is set (any constraining match flag or format_sed — see
653 // detail::replace_stays_real), OR the format uses `$0` (platform-variant, format_forces_std).
654 // Only then does the real expander run.
656 || detail::format_forces_std(std::string_view {fmt})) {
657 return std::regex_replace(s, re.std_engine(), fmt, detail::to_std_match(flags));
658 }
659 const real::regex& engine {std::get<real::regex>(re.engine())};
660 const std::string_view text {s};
661 std::string out;
662 const bool first_only {(flags & regex_constants::format_first_only) != 0U};
663 const bool no_copy {(flags & regex_constants::format_no_copy) != 0U};
664 std::size_t last_end {0};
665 bool done {false};
666 // POSIX ERE iterates with leftmost-longest bounds (find_iter_longest); the ECMAScript default keeps
667 // leftmost-first. Both yield the same match type, so the range-for binds either.
668 const auto matches {re.posix_longest() ? engine.find_iter_longest(text) : engine.find_iter(text)};
669 for (const auto& match : matches) {
670 if (done) {
671 break;
672 }
673 const std::size_t prefix_start {last_end};
674 if (!no_copy) {
675 out.append(text.substr(last_end, match.start() - last_end));
676 }
677 detail::expand_format(out, match, std::string_view {fmt}, text, prefix_start);
678 last_end = match.end();
679 if (first_only) {
680 done = true;
681 }
682 }
683 if (!no_copy) {
684 out.append(text.substr(last_end));
685 }
686 return out;
687 }
688 }
689
691 template <typename CharT, typename Traits>
692 std::basic_string<CharT> regex_replace(const std::basic_string<CharT>& s,
694 const CharT * fmt,
696 {
697 return regex_replace(s, re, std::basic_string<CharT>(fmt), flags);
698 }
699
701 template <typename OutputIt, typename BidirIt, typename CharT, typename Traits>
702 OutputIt regex_replace(OutputIt out,
703 BidirIt first,
704 BidirIt last,
706 const std::basic_string<CharT>& fmt,
708 {
709 const std::basic_string<CharT> result {regex_replace(std::basic_string<CharT>(first, last), re, fmt, flags)};
710 return std::copy(result.begin(), result.end(), out);
711 }
712
713 // --- regex_iterator ----------------------------------------------------------------------
714} // namespace real::compat
715
716#endif // REAL_STD_REGEX_MATCH_HPP
constexpr bool matched() const
Returns true if the attempt matched.
Definition real.hpp:134
A compiled regular expression, parameterized on its storage policy.
Definition real.hpp:468
constexpr result_type fullmatch(std::string_view text) const
Match the entire text (Python re.fullmatch).
Definition real.hpp:507
A std::basic_regex-compatible pattern, backed by real where proven, else std.
bool posix_longest() const noexcept
Whether this is a POSIX-ERE pattern routed to REAL: search/match must use leftmost-**longest** bounds...
const std::basic_regex< CharT, Traits > & std_engine() const
The std::regex for the std / lazy-std path (built once on demand for a real-backed pattern reached vi...
const std::variant< std::basic_regex< CharT, Traits >, real::regex > & engine() const noexcept
Access the active backend (engine-facing; used by the free functions).
bool uses_real_traversal() const noexcept
Whether replace/iterate run on the real traversal (real-backed AND non-nullable). A nullable pattern ...
bool uses_real() const noexcept
True if this regex is backed by the real engine (vs the std fallback).
The result of a match: group sub-matches plus the prefix and suffix.
void fill_from_real(const RealMatch &match)
Fills from real's byte offsets over the sequence [first_, last_). Templated on the match type — real:...
difference_type position(size_type n=0) const
Start offset of group n from the sequence start. For an out-of-range group std anchors the sub_match ...
typename std::iterator_traits< BidirIt >::difference_type difference_type
Distance type.
size_type size() const noexcept
Number of marks (groups), including group 0; 0 when there was no match.
const_iterator cbegin() const
BidirIt last_
End of the searched sequence.
const_iterator iterator
Iterators are const (std parity).
const_iterator end() const
bool ready_
Whether a match is stored.
std::size_t size_type
Size type.
std::vector< value_type, Alloc > groups_
Group sub-matches (0 = whole match).
value_type unmatched_
Sentinel for out-of-range operator[] (anchored at last_).
void fill_from_std(const StdMatch &match)
Copies from a std::match_results (the fallback path) over the same sequence.
BidirIt first_
Start of the searched sequence.
std::basic_string< char_type > string_type
Owning string type.
const_iterator cend() const
typename std::vector< value_type, Alloc >::const_iterator const_iterator
Iterator.
void set_ready_no_match()
Marks a ready but unmatched result — after a failed search/match std leaves ready() == true with size...
string_type str(size_type n=0) const
Matched text of group n (empty if out of range or unmatched).
const_reference operator[](size_type n) const
The sub-match for group n (group 0 is the whole match). Out-of-range n returns a reference to an unma...
typename std::iterator_traits< BidirIt >::value_type char_type
Character type.
value_type suffix_
Unmatched suffix.
bool empty() const noexcept
void rebase_prefix(BidirIt first)
Re-bases the unmatched prefix to start at first — for iteration, where a match's prefix runs from the...
void reset(BidirIt first, BidirIt last)
Resets to the not-ready (no-match) state over the sequence [first, last).
const value_type & suffix() const
The unmatched suffix (whole match end to sequence end).
const_iterator begin() const
difference_type length(size_type n=0) const
Length of group n (0 if out of range or unmatched).
const value_type & prefix() const
The unmatched prefix (sequence start up to the whole match).
value_type prefix_
Unmatched prefix.
bool ready() const noexcept
Whether a successful match has been stored.
A matched sub-expression: a [first, second) range into the searched sequence.
int compare(const string_type &other) const
Three-way length/lexicographic comparison against a string (std::sub_match::compare).
typename std::iterator_traits< BidirIt >::difference_type difference_type
Distance type.
BidirIt iterator
The underlying iterator.
bool matched
Whether this sub-expression participated.
string_type str() const
The matched text as an owned string (empty if it did not participate).
int compare(const sub_match &other) const
std::basic_string_view< value_type > view() const
A non-owning view of the matched text.
std::basic_string< value_type > string_type
The owning string type.
difference_type length() const
Length of the sub-match (0 if it did not participate).
typename std::iterator_traits< BidirIt >::value_type value_type
The character type.
BidirIt second
One past the end of the sub-match.
BidirIt first
Start of the sub-match.
std::regex_constants::match_flag_type to_std_match(regex_constants::match_flag_type f) noexcept
Maps compat match/format flags to std::regex_constants — exhaustive (the std path).
bool format_forces_std(std::string_view fmt) noexcept
Replacement format text that must route to std: $0. $0 is platform-variant (libstdc++ = the whole mat...
bool run_nocapture(BidirIt first, BidirIt last, const basic_regex< CharT, Traits > &re, bool anchored, regex_constants::match_flag_type mf)
Backend run without capturing (no match_results to fill).
void expand_format(std::string &out, const RealMatch &m, std::string_view fmt, std::string_view text, std::size_t prefix_start)
Appends one match's ECMAScript-expanded replacement.
bool replace_stays_real(regex_constants::match_flag_type f) noexcept
Whether regex_replace can run its substitution on real. The real expander honors only format_first_on...
bool run(BidirIt first, BidirIt last, match_results< BidirIt > &m, const basic_regex< CharT, Traits > &re, bool anchored, regex_constants::match_flag_type mf)
Runs the active backend over [first, last) and fills m. anchored selects whole-sequence match (regex_...
bool real_honors(regex_constants::match_flag_type mf) noexcept
Whether real can honor the requested match flags, so the operation may stay on it.
match_flag_type
Match-control flags: the common subset.
@ format_first_only
Replace only the first match.
@ format_no_copy
Do not copy the parts of the text that did not match.
bool regex_match(BidirIt first, BidirIt last, match_results< BidirIt > &m, const basic_regex< CharT, Traits > &re, regex_constants::match_flag_type flags=regex_constants::match_default)
Match of the entire [first, last) (Python re.fullmatch / std::regex_match).
bool regex_search(BidirIt first, BidirIt last, match_results< BidirIt > &m, const basic_regex< CharT, Traits > &re, regex_constants::match_flag_type flags=regex_constants::match_default)
Leftmost search of [first, last) (Python re.search / std::regex_search).
bool operator==(const sub_match< BidirIt > &lhs, const typename sub_match< BidirIt >::string_type &rhs)
Equality against an owned string (the common std::sub_match comparison).
std::basic_string< CharT > regex_replace(const std::basic_string< CharT > &s, const basic_regex< CharT, Traits > &re, const std::basic_string< CharT > &fmt, regex_constants::match_flag_type flags=regex_constants::format_default)
Replaces matches of re in s with the ECMAScript-formatted fmt.
constexpr std::size_t npos
Sentinel for "no position" / unset capture slot (akin to std::string::npos).
Definition program.hpp:33
@ 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
std::regex-compatibility layer, part 1/3: the constants, the error type, the backend-routing screens,...