Commit 5c1c7586 authored by darin@apple.com's avatar darin@apple.com

Reviewed by Mitz.

        - http://bugs.webkit.org/show_bug.cgi?id=15944
          streamline SegmentedString to speed up parsing

        I measured a speed-up of the page load test while developing this patch. I don't
        have a precise figure, though.

        * html/HTMLTokenizer.h: Removed unneeded lineNumberPtr() function. Also renamed
        lineno to m_lineNumber.
        * html/HTMLTokenizer.cpp:
        (WebCore::HTMLTokenizer::processListing): Don't pass 0 to the advance function
        since we don't want to update a line number.
        (WebCore::HTMLTokenizer::parseSpecial): Ditto.
        (WebCore::HTMLTokenizer::parseComment): Pass the line number data member directly
        instead of lineNumberPtr() since the advance function now takes a reference.
        (WebCore::HTMLTokenizer::parseServer): Ditto.
        (WebCore::HTMLTokenizer::parseProcessingInstruction): Ditto.
        (WebCore::HTMLTokenizer::parseText): Ditto.
        (WebCore::HTMLTokenizer::parseEntity): Ditto.
        (WebCore::HTMLTokenizer::parseTag): Ditto.
        (WebCore::HTMLTokenizer::write): Ditto.

        * loader/FTPDirectoryDocument.cpp: (WebCore::FTPDirectoryTokenizer::write):
        * loader/TextDocument.cpp: (WebCore::TextTokenizer::write):
        Don't pass 0 to the advance function.

        * platform/SegmentedString.h: (WebCore::SegmentedString::advance): Streamlined
        the most common case, and pushed less common cases into a separate function
        that is not inlined. Also got rid of a branch by separating the case with a
        line number from the case without one.

        * platform/SegmentedString.cpp: (WebCore::SegmentedString::advanceSlowCase):
        Added. The aforementioned less common cases are here.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@27699 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ef506fee
2007-11-11 Darin Adler <darin@apple.com>
Reviewed by Mitz.
- http://bugs.webkit.org/show_bug.cgi?id=15944
streamline SegmentedString to speed up parsing
I measured a speed-up of the page load test while developing this patch. I don't
have a precise figure, though.
* html/HTMLTokenizer.h: Removed unneeded lineNumberPtr() function. Also renamed
lineno to m_lineNumber.
* html/HTMLTokenizer.cpp:
(WebCore::HTMLTokenizer::processListing): Don't pass 0 to the advance function
since we don't want to update a line number.
(WebCore::HTMLTokenizer::parseSpecial): Ditto.
(WebCore::HTMLTokenizer::parseComment): Pass the line number data member directly
instead of lineNumberPtr() since the advance function now takes a reference.
(WebCore::HTMLTokenizer::parseServer): Ditto.
(WebCore::HTMLTokenizer::parseProcessingInstruction): Ditto.
(WebCore::HTMLTokenizer::parseText): Ditto.
(WebCore::HTMLTokenizer::parseEntity): Ditto.
(WebCore::HTMLTokenizer::parseTag): Ditto.
(WebCore::HTMLTokenizer::write): Ditto.
* loader/FTPDirectoryDocument.cpp: (WebCore::FTPDirectoryTokenizer::write):
* loader/TextDocument.cpp: (WebCore::TextTokenizer::write):
Don't pass 0 to the advance function.
* platform/SegmentedString.h: (WebCore::SegmentedString::advance): Streamlined
the most common case, and pushed less common cases into a separate function
that is not inlined. Also got rid of a branch by separating the case with a
line number from the case without one.
* platform/SegmentedString.cpp: (WebCore::SegmentedString::advanceSlowCase):
Added. The aforementioned less common cases are here.
2007-11-11 Antti Koivisto <antti@apple.com>
Forgot to do this review change (and test HTTP commit).
......
......@@ -242,7 +242,7 @@ void HTMLTokenizer::begin()
noMoreData = false;
brokenComments = false;
brokenServer = false;
lineno = 0;
m_lineNumber = 0;
scriptStartLineno = 0;
tagStartLineno = 0;
m_state.setForceSynchronous(false);
......@@ -261,7 +261,7 @@ HTMLTokenizer::State HTMLTokenizer::processListing(SegmentedString list, State s
if (state.skipLF()) {
state.setSkipLF(false);
if (*list == '\n') {
list.advance(0);
list.advance();
continue;
}
}
......@@ -279,11 +279,11 @@ HTMLTokenizer::State HTMLTokenizer::processListing(SegmentedString list, State s
if (*list == '\r')
state.setSkipLF(true);
list.advance(0);
list.advance();
} else {
state.setDiscardLF(false);
*dest++ = *list;
list.advance(0);
list.advance();
}
}
......@@ -296,7 +296,7 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta
ASSERT(!state.hasTagState());
ASSERT(state.inXmp() + state.inTextArea() + state.inTitle() + state.inStyle() + state.inScript() == 1 );
if (state.inScript())
scriptStartLineno = lineno;
scriptStartLineno = m_lineNumber;
if (state.inComment())
state = parseComment(src, state);
......@@ -311,7 +311,7 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta
continue;
}
if (scriptCodeResync && !tquote && ch == '>') {
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
scriptCodeSize = scriptCodeResync-1;
scriptCodeResync = 0;
scriptCode[ scriptCodeSize ] = scriptCode[ scriptCodeSize + 1 ] = 0;
......@@ -363,12 +363,12 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta
state.setEscaped(!state.escaped() && ch == '\\');
if (!scriptCodeResync && (state.inTextArea() || state.inTitle()) && !src.escaped() && ch == '&') {
UChar* scriptCodeDest = scriptCode+scriptCodeSize;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
state = parseEntity(src, scriptCodeDest, state, m_cBufferPos, true, false);
scriptCodeSize = scriptCodeDest-scriptCode;
} else {
scriptCode[scriptCodeSize++] = *src;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
}
......@@ -578,7 +578,7 @@ HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString &src, State sta
endCharsCount = 4;
}
if (handleBrokenComments || endCharsCount > 1) {
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
if (!(state.inTitle() || state.inScript() || state.inXmp() || state.inTextArea() || state.inStyle())) {
checkScriptBuffer();
scriptCode[scriptCodeSize] = 0;
......@@ -596,7 +596,7 @@ HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString &src, State sta
return state; // Finished parsing comment
}
}
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
return state;
......@@ -609,12 +609,12 @@ HTMLTokenizer::State HTMLTokenizer::parseServer(SegmentedString& src, State stat
scriptCode[scriptCodeSize++] = *src;
if (*src == '>' &&
scriptCodeSize > 1 && scriptCode[scriptCodeSize-2] == '%') {
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
state.setInServer(false);
scriptCodeSize = 0;
return state; // Finished parsing server include
}
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
return state;
}
......@@ -634,11 +634,11 @@ HTMLTokenizer::State HTMLTokenizer::parseProcessingInstruction(SegmentedString &
else if (chbegin == '>' && (!tquote || oldchar == '?')) {
// We got a '?>' sequence
state.setInProcessingInstruction(false);
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
state.setDiscardLF(true);
return state; // Finished parsing comment!
}
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
oldchar = chbegin;
}
......@@ -653,7 +653,7 @@ HTMLTokenizer::State HTMLTokenizer::parseText(SegmentedString &src, State state)
if (state.skipLF()) {
state.setSkipLF(false);
if (cc == '\n') {
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
continue;
}
}
......@@ -666,7 +666,7 @@ HTMLTokenizer::State HTMLTokenizer::parseText(SegmentedString &src, State state)
*dest++ = '\n';
} else
*dest++ = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
return state;
......@@ -693,7 +693,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
case SearchEntity:
if(cc == '#') {
cBuffer[cBufferPos++] = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
state.setEntityState(NumericSearch);
}
else
......@@ -704,7 +704,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
case NumericSearch:
if (cc == 'x' || cc == 'X') {
cBuffer[cBufferPos++] = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
state.setEntityState(Hexadecimal);
} else if (cc >= '0' && cc <= '9')
state.setEntityState(Decimal);
......@@ -727,7 +727,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
digit = (cc - 'A' + 10) & 0xF; // handle both upper and lower case without a branch
EntityUnicodeValue = EntityUnicodeValue * 16 + digit;
cBuffer[cBufferPos++] = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
if (cBufferPos == 10)
state.setEntityState(SearchSemicolon);
......@@ -746,7 +746,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
EntityUnicodeValue = EntityUnicodeValue * 10 + (cc - '0');
cBuffer[cBufferPos++] = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
if (cBufferPos == 9)
state.setEntityState(SearchSemicolon);
......@@ -764,7 +764,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
}
cBuffer[cBufferPos++] = cc;
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
if (cBufferPos == 9)
state.setEntityState(SearchSemicolon);
......@@ -787,7 +787,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
if (EntityUnicodeValue > 0 && EntityUnicodeValue <= 0x10FFFF) {
if (!inViewSourceMode()) {
if (*src == ';')
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
if (EntityUnicodeValue <= 0xFFFF) {
checkBuffer();
src.push(fixUpChar(EntityUnicodeValue));
......@@ -806,7 +806,7 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de
dest += cBufferPos;
if (*src == ';') {
*dest++ = ';';
src.advance(lineNumberPtr());
src.advance(m_lineNumber);
}
}
} else {
......@@ -832,7 +832,6 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
unsigned cBufferPos = m_cBufferPos;
int* lineNoPtr = lineNumberPtr();
bool lastIsSlash = false;
while (!src.isEmpty()) {
......@@ -859,7 +858,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
kdDebug( 6036 ) << "Found comment" << endl;
#endif
// Found '<!--' sequence
src.advance(lineNoPtr);
src.advance(m_lineNumber);
dest = buffer; // ignore the previous part of this tag
state.setInComment(true);
state.setTagState(NoTag);
......@@ -869,7 +868,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
// can handle this case. Only do this in quirks mode. -dwh
if (!src.isEmpty() && *src == '>' && m_doc->inCompatMode()) {
state.setInComment(false);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
if (!src.isEmpty())
// cuts off high bits, which is okay
cBuffer[cBufferPos++] = *src;
......@@ -882,7 +881,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
}
// cuts off high bits, which is okay
cBuffer[cBufferPos++] = *src;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
break;
}
else
......@@ -903,7 +902,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
cBuffer[cBufferPos++] = curchar + ('a' - 'A');
else
cBuffer[cBufferPos++] = curchar;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
// Disadvantage: we add the possible rest of the tag
......@@ -957,7 +956,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
}
if (inViewSourceMode())
currToken.addViewSourceChar(curchar);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
break;
case AttributeName:
......@@ -987,7 +986,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
else
cBuffer[cBufferPos++] = curchar;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
if ( cBufferPos == CBUFLEN ) {
cBuffer[cBufferPos] = '\0';
......@@ -1024,7 +1023,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
state.setTagState(SearchValue);
if (inViewSourceMode())
currToken.addViewSourceChar(curchar);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
else {
currToken.addAttribute(m_doc, attrName, emptyAtom, inViewSourceMode());
......@@ -1039,7 +1038,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
lastIsSlash = curchar == '/';
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
break;
case SearchValue:
......@@ -1051,7 +1050,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
state.setTagState(QuotedValue);
if (inViewSourceMode())
currToken.addViewSourceChar(curchar);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
} else
state.setTagState(Value);
......@@ -1059,7 +1058,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
}
if (inViewSourceMode())
currToken.addViewSourceChar(curchar);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
break;
case QuotedValue:
......@@ -1095,7 +1094,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
// ### attributes like '&{blaa....};' are supposed to be treated as jscript.
if ( curchar == '&' )
{
src.advance(lineNoPtr);
src.advance(m_lineNumber);
state = parseEntity(src, dest, state, cBufferPos, true, true);
break;
}
......@@ -1118,12 +1117,12 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
tquote = NoQuote;
if (inViewSourceMode())
currToken.addViewSourceChar(curchar);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
break;
}
}
*dest++ = *src;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
break;
case Value:
......@@ -1137,7 +1136,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
// parse Entities
if ( curchar == '&' )
{
src.advance(lineNoPtr);
src.advance(m_lineNumber);
state = parseEntity(src, dest, state, cBufferPos, true, true);
break;
}
......@@ -1156,7 +1155,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
}
*dest++ = *src;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
break;
case SearchEnd:
......@@ -1173,7 +1172,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
if (inViewSourceMode())
currToken.addViewSourceChar(*src);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
if (src.isEmpty()) break;
......@@ -1182,7 +1181,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
tquote = NoQuote;
if (*src != '<')
src.advance(lineNoPtr);
src.advance(m_lineNumber);
if (currToken.tagName == nullAtom) { //stop if tag is unknown
m_cBufferPos = cBufferPos;
......@@ -1253,7 +1252,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
searchStopperLen = 7;
State savedState = state;
SegmentedString savedSrc = src;
long savedLineno = lineno;
long savedLineno = m_lineNumber;
state.setInTitle(true);
state = parseSpecial(src, state);
if (state.inTitle() && src.isEmpty()) {
......@@ -1266,7 +1265,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state)
// than a local variable.
state = savedState;
src = savedSrc;
lineno = savedLineno;
m_lineNumber = savedLineno;
scriptCodeSize = 0;
}
}
......@@ -1366,8 +1365,6 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
State state = m_state;
int* lineNoPtr = lineNumberPtr();
while (!src.isEmpty() && (!frame || !frame->loader()->isScheduledLocationChangePending())) {
if (!continueProcessing(processedCount, startTime, state))
break;
......@@ -1382,7 +1379,7 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
state.setSkipLF(false);
if (wasSkipLF && (cc == '\n'))
src.advance(0);
src.advance();
else if (state.needsSpecialWriteHandling()) {
// it's important to keep needsSpecialWriteHandling with the flags this block tests
if (state.hasEntityState())
......@@ -1449,11 +1446,11 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
state = parseTag(src, state);
}
} else if (cc == '&' && !src.escaped()) {
src.advance(lineNoPtr);
src.advance(m_lineNumber);
state = parseEntity(src, dest, state, m_cBufferPos, true, state.hasTagState());
} else if (cc == '<' && !src.escaped()) {
tagStartLineno = lineno;
src.advance(lineNoPtr);
tagStartLineno = m_lineNumber;
src.advance(m_lineNumber);
state.setStartTag(true);
} else if (cc == '\n' || cc == '\r') {
if (state.discardLF())
......@@ -1463,17 +1460,17 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
// Process this LF
*dest++ = '\n';
if (cc == '\r' && !src.excludeLineNumbers())
lineno++;
m_lineNumber++;
}
/* Check for MS-DOS CRLF sequence */
if (cc == '\r')
state.setSkipLF(true);
src.advance(lineNoPtr);
src.advance(m_lineNumber);
} else {
state.setDiscardLF(false);
*dest++ = cc;
src.advance(lineNoPtr);
src.advance(m_lineNumber);
}
}
......@@ -1614,7 +1611,7 @@ PassRefPtr<Node> HTMLTokenizer::processToken()
} else if (currToken.tagName == nullAtom) {
currToken.reset();
if (jsProxy)
jsProxy->setEventHandlerLineno(lineno);
jsProxy->setEventHandlerLineno(m_lineNumber);
return 0;
}
......
......@@ -3,7 +3,7 @@
(C) 1997 Torben Weis (weis@kde.org)
(C) 1998 Waldo Bastian (bastian@kde.org)
(C) 2001 Dirk Mueller (mueller@kde.org)
Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -100,11 +100,9 @@ public:
virtual bool processingData() const;
virtual int executingScript() const { return m_executingScript; }
virtual int lineNumber() const { return lineno; }
virtual int lineNumber() const { return m_lineNumber; }
virtual int columnNumber() const { return 1; }
int* lineNumberPtr() { return &lineno; }
bool processingContentWrittenByScript() const { return src.excludeLineNumbers(); }
virtual void executeScriptsWaitingForStylesheets();
......@@ -333,7 +331,7 @@ private:
// store a flag to get rid of the O(n^2) behaviour in such a case.
bool brokenComments;
// current line number
int lineno;
int m_lineNumber;
// line number at which the current <script> started
int scriptStartLineno;
int tagStartLineno;
......
......@@ -402,7 +402,7 @@ bool FTPDirectoryTokenizer::write(const SegmentedString& s, bool appendData)
m_skipLF = false;
}
str.advance(0);
str.advance();
// Maybe enlarge the buffer
checkBuffer();
......
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -23,7 +23,6 @@
*/
#include "config.h"
#include "TextDocument.h"
#include "Element.h"
......@@ -87,7 +86,7 @@ bool TextTokenizer::write(const SegmentedString& s, bool appendData)
m_skipLF = false;
}
str.advance(0);
str.advance();
// Maybe enlarge the buffer
checkBuffer();
......
/*
This file is part of the KDE libraries
Copyright (C) 2004-6 Apple Computer
Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -174,4 +172,31 @@ String SegmentedString::toString() const
return result;
}
void SegmentedString::advanceSlowCase()
{
if (m_pushedChar1) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
} else if (m_currentString.m_current) {
++m_currentString.m_current;
if (--m_currentString.m_length == 0)
advanceSubstring();
}
m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
}
void SegmentedString::advanceSlowCase(int& lineNumber)
{
if (m_pushedChar1) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
} else if (m_currentString.m_current) {
if (*m_currentString.m_current++ == '\n' && !m_currentString.excludeLineNumbers())
++lineNumber;
if (--m_currentString.m_length == 0)
advanceSubstring();
}
m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
}
}
/*
This file is part of the KDE libraries
Copyright (C) 2004, 2005, 2006 Apple Computer
Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
......@@ -83,7 +81,8 @@ public:
bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); }
void setExcludeLineNumbers();
void push(UChar c) {
void push(UChar c)
{
if (!m_pushedChar1) {
m_pushedChar1 = c;
m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
......@@ -96,17 +95,25 @@ public:
bool isEmpty() const { return !current(); }
unsigned length() const;
void advance(int* lineNumber = 0) {
if (m_pushedChar1) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
} else if (m_currentString.m_current) {
if (*m_currentString.m_current++ == '\n' && lineNumber && !m_currentString.excludeLineNumbers())
*lineNumber = *lineNumber + 1;
if (--m_currentString.m_length == 0)
advanceSubstring();
void advance()
{
if (!m_pushedChar1 && m_currentString.m_length > 1) {
--m_currentString.m_length;
m_currentChar = ++m_currentString.m_current;
return;
}
advanceSlowCase();
}
void advance(int& lineNumber)
{
if (!m_pushedChar1 && m_currentString.m_length > 1) {
lineNumber += (*m_currentString.m_current == '\n') & m_currentString.excludeLineNumbers();
--m_currentString.m_length;
m_currentChar = ++m_currentString.m_current;
return;
}
m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
advanceSlowCase(lineNumber);
}
bool escaped() const { return m_pushedChar1; }
......@@ -120,6 +127,8 @@ private:
void append(const SegmentedSubstring &);
void prepend(const SegmentedSubstring &);
void advanceSlowCase();
void advanceSlowCase(int& lineNumber);
void advanceSubstring();
const UChar* current() const { return m_currentChar; }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment