Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
dart::TextNode Class Reference

#include <regexp.h>

Inheritance diagram for dart::TextNode:
dart::SeqRegExpNode dart::RegExpNode dart::ZoneAllocated

Public Member Functions

 TextNode (ZoneGrowableArray< TextElement > *elms, bool read_backward, RegExpNode *on_success)
 
 TextNode (RegExpCharacterClass *that, bool read_backward, RegExpNode *on_success)
 
virtual void Accept (NodeVisitor *visitor)
 
virtual void Emit (RegExpCompiler *compiler, Trace *trace)
 
virtual intptr_t EatsAtLeast (intptr_t still_to_find, intptr_t budget, bool not_at_start)
 
virtual void GetQuickCheckDetails (QuickCheckDetails *details, RegExpCompiler *compiler, intptr_t characters_filled_in, bool not_at_start)
 
ZoneGrowableArray< TextElement > * elements ()
 
bool read_backward ()
 
void MakeCaseIndependent (bool is_one_byte)
 
virtual intptr_t GreedyLoopTextLength ()
 
virtual RegExpNodeGetSuccessorOfOmnivorousTextNode (RegExpCompiler *compiler)
 
virtual void FillInBMInfo (intptr_t offset, intptr_t budget, BoyerMooreLookahead *bm, bool not_at_start)
 
void CalculateOffsets ()
 
virtual RegExpNodeFilterOneByte (intptr_t depth)
 
- Public Member Functions inherited from dart::SeqRegExpNode
 SeqRegExpNode (RegExpNode *on_success)
 
RegExpNodeon_success ()
 
void set_on_success (RegExpNode *node)
 
virtual RegExpNodeFilterOneByte (intptr_t depth)
 
virtual void FillInBMInfo (intptr_t offset, intptr_t budget, BoyerMooreLookahead *bm, bool not_at_start)
 
- Public Member Functions inherited from dart::RegExpNode
 RegExpNode (Zone *zone)
 
virtual ~RegExpNode ()
 
virtual void Accept (NodeVisitor *visitor)=0
 
virtual void Emit (RegExpCompiler *compiler, Trace *trace)=0
 
virtual intptr_t EatsAtLeast (intptr_t still_to_find, intptr_t budget, bool not_at_start)=0
 
bool EmitQuickCheck (RegExpCompiler *compiler, Trace *bounds_check_trace, Trace *trace, bool preload_has_checked_bounds, BlockLabel *on_possible_success, QuickCheckDetails *details_return, bool fall_through_on_failure)
 
virtual void GetQuickCheckDetails (QuickCheckDetails *details, RegExpCompiler *compiler, intptr_t characters_filled_in, bool not_at_start)=0
 
virtual intptr_t GreedyLoopTextLength ()
 
virtual RegExpNodeGetSuccessorOfOmnivorousTextNode (RegExpCompiler *compiler)
 
virtual void FillInBMInfo (intptr_t offset, intptr_t budget, BoyerMooreLookahead *bm, bool not_at_start)
 
virtual RegExpNodeFilterOneByte (intptr_t depth)
 
RegExpNodereplacement ()
 
RegExpNodeset_replacement (RegExpNode *replacement)
 
void SaveBMInfo (BoyerMooreLookahead *bm, bool not_at_start, intptr_t offset)
 
BlockLabellabel ()
 
NodeInfoinfo ()
 
BoyerMooreLookaheadbm_info (bool not_at_start)
 
Zonezone () const
 
- Public Member Functions inherited from dart::ZoneAllocated
 ZoneAllocated ()
 
void * operator new (size_t size)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer)
 

Static Public Member Functions

static TextNodeCreateForCharacterRanges (ZoneGrowableArray< CharacterRange > *ranges, bool read_backward, RegExpNode *on_success, RegExpFlags flags)
 
static TextNodeCreateForSurrogatePair (CharacterRange lead, CharacterRange trail, bool read_backward, RegExpNode *on_success, RegExpFlags flags)
 

Additional Inherited Members

- Static Public Attributes inherited from dart::RegExpNode
static constexpr intptr_t kNodeIsTooComplexForGreedyLoops = -1
 
static constexpr intptr_t kRecursionBudget = 200
 
static constexpr intptr_t kMaxCopiesCodeGenerated = 10
 
- Protected Types inherited from dart::RegExpNode
enum  LimitResult { DONE , CONTINUE }
 
- Protected Member Functions inherited from dart::SeqRegExpNode
RegExpNodeFilterSuccessor (intptr_t depth)
 
- Protected Member Functions inherited from dart::RegExpNode
LimitResult LimitVersions (RegExpCompiler *compiler, Trace *trace)
 
void set_bm_info (bool not_at_start, BoyerMooreLookahead *bm)
 
- Protected Attributes inherited from dart::RegExpNode
RegExpNodereplacement_
 

Detailed Description

Definition at line 650 of file regexp.h.

Constructor & Destructor Documentation

◆ TextNode() [1/2]

dart::TextNode::TextNode ( ZoneGrowableArray< TextElement > *  elms,
bool  read_backward,
RegExpNode on_success 
)
inline

Definition at line 652 of file regexp.h.

655 : SeqRegExpNode(on_success), elms_(elms), read_backward_(read_backward) {}
RegExpNode * on_success()
Definition: regexp.h:544
SeqRegExpNode(RegExpNode *on_success)
Definition: regexp.h:542
bool read_backward()
Definition: regexp.h:687

◆ TextNode() [2/2]

dart::TextNode::TextNode ( RegExpCharacterClass that,
bool  read_backward,
RegExpNode on_success 
)
inline

Definition at line 656 of file regexp.h.

660 elms_(new(zone()) ZoneGrowableArray<TextElement>(1)),
661 read_backward_(read_backward) {
662 elms_->Add(TextElement::CharClass(that));
663 }
Zone * zone() const
Definition: regexp.h:483
static TextElement CharClass(RegExpCharacterClass *char_class)
Definition: regexp.cc:229

Member Function Documentation

◆ Accept()

virtual void dart::TextNode::Accept ( NodeVisitor visitor)
virtual

Implements dart::RegExpNode.

◆ CalculateOffsets()

void dart::TextNode::CalculateOffsets ( )

Definition at line 5104 of file regexp.cc.

5104 {
5105 intptr_t element_count = elements()->length();
5106 // Set up the offsets of the elements relative to the start. This is a fixed
5107 // quantity since a TextNode can only contain fixed-width things.
5108 intptr_t cp_offset = 0;
5109 for (intptr_t i = 0; i < element_count; i++) {
5110 TextElement& elm = (*elements())[i];
5111 elm.set_cp_offset(cp_offset);
5112 cp_offset += elm.length();
5113 }
5114}
ZoneGrowableArray< TextElement > * elements()
Definition: regexp.h:686

◆ CreateForCharacterRanges()

TextNode * dart::TextNode::CreateForCharacterRanges ( ZoneGrowableArray< CharacterRange > *  ranges,
bool  read_backward,
RegExpNode on_success,
RegExpFlags  flags 
)
static

Definition at line 2480 of file regexp.cc.

2484 {
2485 ASSERT(ranges != nullptr);
2486 ZoneGrowableArray<TextElement>* elms = new ZoneGrowableArray<TextElement>(1);
2487 elms->Add(TextElement::CharClass(new RegExpCharacterClass(ranges, flags)));
2488 return new TextNode(elms, read_backward, on_success);
2489}
TextNode(ZoneGrowableArray< TextElement > *elms, bool read_backward, RegExpNode *on_success)
Definition: regexp.h:652
#define ASSERT(E)
FlutterSemanticsFlag flags

◆ CreateForSurrogatePair()

TextNode * dart::TextNode::CreateForSurrogatePair ( CharacterRange  lead,
CharacterRange  trail,
bool  read_backward,
RegExpNode on_success,
RegExpFlags  flags 
)
static

Definition at line 2491 of file regexp.cc.

2495 {
2496 auto lead_ranges = CharacterRange::List(on_success->zone(), lead);
2497 auto trail_ranges = CharacterRange::List(on_success->zone(), trail);
2498 auto elms = new ZoneGrowableArray<TextElement>(2);
2499
2500 elms->Add(
2501 TextElement::CharClass(new RegExpCharacterClass(lead_ranges, flags)));
2502 elms->Add(
2503 TextElement::CharClass(new RegExpCharacterClass(trail_ranges, flags)));
2504
2505 return new TextNode(elms, read_backward, on_success);
2506}
static ZoneGrowableArray< CharacterRange > * List(Zone *zone, CharacterRange range)
Definition: regexp.h:47

◆ EatsAtLeast()

intptr_t dart::TextNode::EatsAtLeast ( intptr_t  still_to_find,
intptr_t  budget,
bool  not_at_start 
)
virtual

Implements dart::RegExpNode.

Definition at line 1524 of file regexp.cc.

1526 {
1527 if (read_backward()) return 0;
1528 intptr_t answer = Length();
1529 if (answer >= still_to_find) return answer;
1530 if (budget <= 0) return answer;
1531 // We are not at start after this node so we set the last argument to 'true'.
1532 return answer +
1533 on_success()->EatsAtLeast(still_to_find - answer, budget - 1, true);
1534}
virtual intptr_t EatsAtLeast(intptr_t still_to_find, intptr_t budget, bool not_at_start)=0

◆ elements()

ZoneGrowableArray< TextElement > * dart::TextNode::elements ( )
inline

Definition at line 686 of file regexp.h.

686{ return elms_; }

◆ Emit()

void dart::TextNode::Emit ( RegExpCompiler compiler,
Trace trace 
)
virtual

Implements dart::RegExpNode.

Definition at line 2514 of file regexp.cc.

2514 {
2515 LimitResult limit_result = LimitVersions(compiler, trace);
2516 if (limit_result == DONE) return;
2517 ASSERT(limit_result == CONTINUE);
2518
2519 if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) {
2520 compiler->SetRegExpTooBig();
2521 return;
2522 }
2523
2524 if (compiler->one_byte()) {
2525 intptr_t dummy = 0;
2526 TextEmitPass(compiler, NON_LATIN1_MATCH, false, trace, false, &dummy);
2527 }
2528
2529 bool first_elt_done = false;
2530 intptr_t bound_checked_to = trace->cp_offset() - 1;
2531 bound_checked_to += trace->bound_checked_up_to();
2532
2533 // If a character is preloaded into the current character register then
2534 // check that now.
2535 if (trace->characters_preloaded() == 1) {
2536 for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
2537 TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), true, trace,
2538 false, &bound_checked_to);
2539 }
2540 first_elt_done = true;
2541 }
2542
2543 for (intptr_t pass = kFirstRealPass; pass <= kLastPass; pass++) {
2544 TextEmitPass(compiler, static_cast<TextEmitPassType>(pass), false, trace,
2545 first_elt_done, &bound_checked_to);
2546 }
2547
2548 Trace successor_trace(*trace);
2549 // If we advance backward, we may end up at the start.
2550 successor_trace.AdvanceCurrentPositionInTrace(
2551 read_backward() ? -Length() : Length(), compiler);
2552 successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN
2554 RecursionCheck rc(compiler);
2555 on_success()->Emit(compiler, &successor_trace);
2556}
static constexpr intptr_t kMaxCPOffset
virtual void Emit(RegExpCompiler *compiler, Trace *trace)=0
LimitResult LimitVersions(RegExpCompiler *compiler, Trace *trace)
Definition: regexp.cc:1431
@ FALSE_VALUE
Definition: regexp.h:1206

◆ FillInBMInfo()

void dart::TextNode::FillInBMInfo ( intptr_t  offset,
intptr_t  budget,
BoyerMooreLookahead bm,
bool  not_at_start 
)
virtual

Reimplemented from dart::SeqRegExpNode.

Definition at line 5203 of file regexp.cc.

5206 {
5207 if (initial_offset >= bm->length()) return;
5208 intptr_t offset = initial_offset;
5209 intptr_t max_char = bm->max_char();
5210 for (intptr_t i = 0; i < elements()->length(); i++) {
5211 if (offset >= bm->length()) {
5212 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5213 return;
5214 }
5215 TextElement text = elements()->At(i);
5216 if (text.text_type() == TextElement::ATOM) {
5217 RegExpAtom* atom = text.atom();
5218 for (intptr_t j = 0; j < atom->length(); j++, offset++) {
5219 if (offset >= bm->length()) {
5220 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5221 return;
5222 }
5223 uint16_t character = atom->data()->At(j);
5224 if (atom->flags().IgnoreCase()) {
5227 character, bm->max_char() == Symbols::kMaxOneCharCodeSymbol,
5228 chars);
5229 for (intptr_t j = 0; j < length; j++) {
5230 bm->Set(offset, chars[j]);
5231 }
5232 } else {
5233 if (character <= max_char) bm->Set(offset, character);
5234 }
5235 }
5236 } else {
5237 ASSERT(text.text_type() == TextElement::CHAR_CLASS);
5238 RegExpCharacterClass* char_class = text.char_class();
5239 ZoneGrowableArray<CharacterRange>* ranges = char_class->ranges();
5240 if (char_class->is_negated()) {
5241 bm->SetAll(offset);
5242 } else {
5243 for (intptr_t k = 0; k < ranges->length(); k++) {
5244 const CharacterRange& range = ranges->At(k);
5245 if (range.from() > max_char) continue;
5246 intptr_t to =
5247 Utils::Minimum(max_char, static_cast<intptr_t>(range.to()));
5248 bm->SetInterval(offset, Interval(range.from(), to));
5249 }
5250 }
5251 offset++;
5252 }
5253 }
5254 if (offset >= bm->length()) {
5255 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5256 return;
5257 }
5258 on_success()->FillInBMInfo(offset, budget - 1, bm,
5259 true); // Not at start after a text node.
5260 if (initial_offset == 0) set_bm_info(not_at_start, bm);
5261}
void set_bm_info(bool not_at_start, BoyerMooreLookahead *bm)
Definition: regexp.h:491
virtual void FillInBMInfo(intptr_t offset, intptr_t budget, BoyerMooreLookahead *bm, bool not_at_start)
Definition: regexp.h:439
@ kMaxOneCharCodeSymbol
Definition: symbols.h:577
static T Minimum(T x, T y)
Definition: utils.h:36
size_t length
std::u16string text
static intptr_t GetCaseIndependentLetters(uint16_t character, bool one_byte_subject, int32_t *letters)
Definition: regexp.cc:861
SeparatedVector2 offset
static constexpr intptr_t kMaxWidth
Definition: unibrow.h:56

◆ FilterOneByte()

RegExpNode * dart::TextNode::FilterOneByte ( intptr_t  depth)
virtual

Reimplemented from dart::SeqRegExpNode.

Definition at line 1977 of file regexp.cc.

1977 {
1978 if (info()->replacement_calculated) return replacement();
1979 if (depth < 0) return this;
1980 ASSERT(!info()->visited);
1981 VisitMarker marker(info());
1982 intptr_t element_count = elms_->length();
1983 for (intptr_t i = 0; i < element_count; i++) {
1984 TextElement elm = elms_->At(i);
1985 if (elm.text_type() == TextElement::ATOM) {
1986 ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
1987 for (intptr_t j = 0; j < quarks->length(); j++) {
1988 uint16_t c = quarks->At(j);
1989 if (c <= Symbols::kMaxOneCharCodeSymbol) continue;
1990 if (!elm.atom()->ignore_case()) return set_replacement(nullptr);
1991 // Here, we need to check for characters whose upper and lower cases
1992 // are outside the Latin-1 range.
1993 uint16_t converted = ConvertNonLatin1ToLatin1(c);
1994 // Character is outside Latin-1 completely
1995 if (converted == 0) return set_replacement(nullptr);
1996 // Convert quark to Latin-1 in place.
1997 (*quarks)[0] = converted;
1998 }
1999 } else {
2000 ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
2001 RegExpCharacterClass* cc = elm.char_class();
2002 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
2003 if (!CharacterRange::IsCanonical(ranges)) {
2005 }
2006 // Now they are in order so we only need to look at the first.
2007 intptr_t range_count = ranges->length();
2008 if (cc->is_negated()) {
2009 if (range_count != 0 && ranges->At(0).from() == 0 &&
2010 ranges->At(0).to() >= Symbols::kMaxOneCharCodeSymbol) {
2011 // This will be handled in a later filter.
2012 if (cc->flags().IgnoreCase() &&
2014 continue;
2015 }
2016 return set_replacement(nullptr);
2017 }
2018 } else {
2019 if (range_count == 0 ||
2020 ranges->At(0).from() > Symbols::kMaxOneCharCodeSymbol) {
2021 // This will be handled in a later filter.
2022 if (cc->flags().IgnoreCase() &&
2024 continue;
2025 return set_replacement(nullptr);
2026 }
2027 }
2028 }
2029 }
2030 return FilterSuccessor(depth - 1);
2031}
static const char marker[]
static bool IsCanonical(ZoneGrowableArray< CharacterRange > *ranges)
Definition: regexp.cc:4772
static void Canonicalize(ZoneGrowableArray< CharacterRange > *ranges)
Definition: regexp.cc:4876
NodeInfo * info()
Definition: regexp.h:477
RegExpNode * set_replacement(RegExpNode *replacement)
Definition: regexp.h:455
RegExpNode * replacement()
Definition: regexp.h:451
RegExpNode * FilterSuccessor(intptr_t depth)
Definition: regexp.cc:1939
static uint16_t ConvertNonLatin1ToLatin1(uint16_t c)
Definition: regexp.cc:1962
static bool RangesContainLatin1Equivalents(ZoneGrowableArray< CharacterRange > *ranges)
Definition: regexp.cc:1953

◆ GetQuickCheckDetails()

void dart::TextNode::GetQuickCheckDetails ( QuickCheckDetails details,
RegExpCompiler compiler,
intptr_t  characters_filled_in,
bool  not_at_start 
)
virtual

Implements dart::RegExpNode.

Definition at line 1700 of file regexp.cc.

1703 {
1704#if defined(__GNUC__) && defined(__BYTE_ORDER__)
1705 // TODO(zerny): Make the combination code byte-order independent.
1706 ASSERT(details->characters() == 1 ||
1707 (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
1708#endif
1709 // Do not collect any quick check details if the text node reads backward,
1710 // since it reads in the opposite direction than we use for quick checks.
1711 if (read_backward()) return;
1712 ASSERT(characters_filled_in < details->characters());
1713 intptr_t characters = details->characters();
1714 int32_t char_mask;
1715 if (compiler->one_byte()) {
1717 } else {
1718 char_mask = Utf16::kMaxCodeUnit;
1719 }
1720 for (intptr_t k = 0; k < elms_->length(); k++) {
1721 TextElement elm = elms_->At(k);
1722 if (elm.text_type() == TextElement::ATOM) {
1723 ZoneGrowableArray<uint16_t>* quarks = elm.atom()->data();
1724 for (intptr_t i = 0; i < characters && i < quarks->length(); i++) {
1725 QuickCheckDetails::Position* pos =
1726 details->positions(characters_filled_in);
1727 uint16_t c = quarks->At(i);
1728 if (c > char_mask) {
1729 // If we expect a non-Latin1 character from an one-byte string,
1730 // there is no way we can match. Not even case independent
1731 // matching can turn an Latin1 character into non-Latin1 or
1732 // vice versa.
1733 // TODO(dcarney): issue 3550. Verify that this works as expected.
1734 // For example, \u0178 is uppercase of \u00ff (y-umlaut).
1735 details->set_cannot_match();
1736 pos->determines_perfectly = false;
1737 return;
1738 }
1739 if (elm.atom()->ignore_case()) {
1741 intptr_t length =
1742 GetCaseIndependentLetters(c, compiler->one_byte(), chars);
1743 ASSERT(length != 0); // Can only happen if c > char_mask (see above).
1744 if (length == 1) {
1745 // This letter has no case equivalents, so it's nice and simple
1746 // and the mask-compare will determine definitely whether we have
1747 // a match at this character position.
1748 pos->mask = char_mask;
1749 pos->value = c;
1750 pos->determines_perfectly = true;
1751 } else {
1752 uint32_t common_bits = char_mask;
1753 uint32_t bits = chars[0];
1754 for (intptr_t j = 1; j < length; j++) {
1755 uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
1756 common_bits ^= differing_bits;
1757 bits &= common_bits;
1758 }
1759 // If length is 2 and common bits has only one zero in it then
1760 // our mask and compare instruction will determine definitely
1761 // whether we have a match at this character position. Otherwise
1762 // it can only be an approximate check.
1763 uint32_t one_zero = (common_bits | ~char_mask);
1764 if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
1765 pos->determines_perfectly = true;
1766 }
1767 pos->mask = common_bits;
1768 pos->value = bits;
1769 }
1770 } else {
1771 // Don't ignore case. Nice simple case where the mask-compare will
1772 // determine definitely whether we have a match at this character
1773 // position.
1774 pos->mask = char_mask;
1775 pos->value = c;
1776 pos->determines_perfectly = true;
1777 }
1778 characters_filled_in++;
1779 ASSERT(characters_filled_in <= details->characters());
1780 if (characters_filled_in == details->characters()) {
1781 return;
1782 }
1783 }
1784 } else {
1785 QuickCheckDetails::Position* pos =
1786 details->positions(characters_filled_in);
1787 RegExpCharacterClass* tree = elm.char_class();
1788 ZoneGrowableArray<CharacterRange>* ranges = tree->ranges();
1789 ASSERT(!ranges->is_empty());
1790 if (!CharacterRange::IsCanonical(ranges)) {
1792 }
1793 if (tree->is_negated()) {
1794 // A quick check uses multi-character mask and compare. There is no
1795 // useful way to incorporate a negative char class into this scheme
1796 // so we just conservatively create a mask and value that will always
1797 // succeed.
1798 pos->mask = 0;
1799 pos->value = 0;
1800 } else {
1801 intptr_t first_range = 0;
1802 while (ranges->At(first_range).from() > char_mask) {
1803 first_range++;
1804 if (first_range == ranges->length()) {
1805 details->set_cannot_match();
1806 pos->determines_perfectly = false;
1807 return;
1808 }
1809 }
1810 CharacterRange range = ranges->At(first_range);
1811 uint16_t from = range.from();
1812 uint16_t to = range.to();
1813 if (to > char_mask) {
1814 to = char_mask;
1815 }
1816 uint32_t differing_bits = (from ^ to);
1817 // A mask and compare is only perfect if the differing bits form a
1818 // number like 00011111 with one single block of trailing 1s.
1819 if ((differing_bits & (differing_bits + 1)) == 0 &&
1820 from + differing_bits == to) {
1821 pos->determines_perfectly = true;
1822 }
1823 uint32_t common_bits = ~SmearBitsRight(differing_bits);
1824 uint32_t bits = (from & common_bits);
1825 for (intptr_t i = first_range + 1; i < ranges->length(); i++) {
1826 CharacterRange range = ranges->At(i);
1827 uint16_t from = range.from();
1828 uint16_t to = range.to();
1829 if (from > char_mask) continue;
1830 if (to > char_mask) to = char_mask;
1831 // Here we are combining more ranges into the mask and compare
1832 // value. With each new range the mask becomes more sparse and
1833 // so the chances of a false positive rise. A character class
1834 // with multiple ranges is assumed never to be equivalent to a
1835 // mask and compare operation.
1836 pos->determines_perfectly = false;
1837 uint32_t new_common_bits = (from ^ to);
1838 new_common_bits = ~SmearBitsRight(new_common_bits);
1839 common_bits &= new_common_bits;
1840 bits &= new_common_bits;
1841 uint32_t differing_bits = (from & common_bits) ^ bits;
1842 common_bits ^= differing_bits;
1843 bits &= common_bits;
1844 }
1845 pos->mask = common_bits;
1846 pos->value = bits;
1847 }
1848 characters_filled_in++;
1849 ASSERT(characters_filled_in <= details->characters());
1850 if (characters_filled_in == details->characters()) {
1851 return;
1852 }
1853 }
1854 }
1855 ASSERT(characters_filled_in != details->characters());
1856 if (!details->cannot_match()) {
1857 on_success()->GetQuickCheckDetails(details, compiler, characters_filled_in,
1858 true);
1859 }
1860}
SkPoint pos
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, intptr_t characters_filled_in, bool not_at_start)=0
static constexpr int32_t kMaxCodeUnit
Definition: unicode.h:158

◆ GetSuccessorOfOmnivorousTextNode()

RegExpNode * dart::TextNode::GetSuccessorOfOmnivorousTextNode ( RegExpCompiler compiler)
virtual

Reimplemented from dart::RegExpNode.

Definition at line 2604 of file regexp.cc.

2605 {
2606 if (read_backward()) return nullptr;
2607 if (elms_->length() != 1) return nullptr;
2608 TextElement elm = elms_->At(0);
2609 if (elm.text_type() != TextElement::CHAR_CLASS) return nullptr;
2610 RegExpCharacterClass* node = elm.char_class();
2611 ZoneGrowableArray<CharacterRange>* ranges = node->ranges();
2612 if (!CharacterRange::IsCanonical(ranges)) {
2614 }
2615 if (node->is_negated()) {
2616 return ranges->length() == 0 ? on_success() : nullptr;
2617 }
2618 if (ranges->length() != 1) return nullptr;
2619 uint32_t max_char;
2620 if (compiler->one_byte()) {
2622 } else {
2623 max_char = Utf16::kMaxCodeUnit;
2624 }
2625 return ranges->At(0).IsEverything(max_char) ? on_success() : nullptr;
2626}

◆ GreedyLoopTextLength()

intptr_t dart::TextNode::GreedyLoopTextLength ( )
virtual

Reimplemented from dart::RegExpNode.

Definition at line 2599 of file regexp.cc.

2599 {
2600 TextElement elm = elms_->At(elms_->length() - 1);
2601 return elm.cp_offset() + elm.length();
2602}

◆ MakeCaseIndependent()

void dart::TextNode::MakeCaseIndependent ( bool  is_one_byte)

Definition at line 2581 of file regexp.cc.

2581 {
2582 intptr_t element_count = elms_->length();
2583 for (intptr_t i = 0; i < element_count; i++) {
2584 TextElement elm = elms_->At(i);
2585 if (elm.text_type() == TextElement::CHAR_CLASS) {
2586 RegExpCharacterClass* cc = elm.char_class();
2587 bool case_equivalents_already_added =
2588 cc->flags().NeedsUnicodeCaseEquivalents();
2589 if (cc->flags().IgnoreCase() && !case_equivalents_already_added) {
2590 // None of the standard character classes is different in the case
2591 // independent case and it slows us down if we don't know that.
2592 if (cc->is_standard()) continue;
2593 CharacterRange::AddCaseEquivalents(cc->ranges(), is_one_byte, Z);
2594 }
2595 }
2596 }
2597}
static void AddCaseEquivalents(ZoneGrowableArray< CharacterRange > *ranges, bool is_one_byte, Zone *zone)
Definition: regexp.cc:4691
#define Z
Definition: regexp.cc:26

◆ read_backward()

bool dart::TextNode::read_backward ( )
inline

Definition at line 687 of file regexp.h.

687{ return read_backward_; }

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