static size_t findPlainTextInternal(CharacterIteratorAlgorithm<Strategy>& it, const String& target, FindOptions options, size_t& matchStart) { matchStart = 0; size_t matchLength = 0; if (!isValidUTF16(target)) return 0; SearchBuffer buffer(target, options); if (buffer.needsMoreContext()) { for (SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator( PositionTemplate<Strategy>::firstPositionInNode( it.ownerDocument()), PositionTemplate<Strategy>(it.currentContainer(), it.startOffset())); !backwardsIterator.atEnd(); backwardsIterator.advance()) { BackwardsTextBuffer characters; backwardsIterator.copyTextTo(&characters); buffer.prependContext(characters.data(), characters.size()); if (!buffer.needsMoreContext()) break; } } while (!it.atEnd()) { // TODO(xiaochengh): Should allow copying text to SearchBuffer directly ForwardsTextBuffer characters; it.copyTextTo(&characters); buffer.append(characters.data(), characters.size()); it.advance(buffer.numberOfCharactersJustAppended()); tryAgain: size_t matchStartOffset; if (size_t newMatchLength = buffer.search(matchStartOffset)) { // Note that we found a match, and where we found it. size_t lastCharacterInBufferOffset = it.characterOffset(); DCHECK_GE(lastCharacterInBufferOffset, matchStartOffset); matchStart = lastCharacterInBufferOffset - matchStartOffset; matchLength = newMatchLength; // If searching forward, stop on the first match. // If searching backward, don't stop, so we end up with the last match. if (!(options & Backwards)) break; goto tryAgain; } if (it.atBreak() && !buffer.atBreak()) { buffer.reachedBreak(); goto tryAgain; } } return matchLength; }
static String extractString(const Element& element) { const EphemeralRangeTemplate<Strategy> range = EphemeralRangeTemplate<Strategy>::rangeOfContents(element); BackwardsTextBuffer buffer; for (SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it( range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) { it.copyTextTo(&buffer); } return String(buffer.data(), buffer.size()); }