diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp index b0b7db7f0b6..eca64080332 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp @@ -721,9 +721,7 @@ CreateSourceText(const PRInt32 aColNumber, } nsresult -nsExpatDriver::HandleError(const char *aBuffer, - PRUint32 aLength, - PRBool aIsFinal) +nsExpatDriver::HandleError() { PRInt32 code = XML_GetErrorCode(mExpatParser); NS_WARN_IF_FALSE(code > XML_ERROR_NONE, "unexpected XML error code"); @@ -761,9 +759,9 @@ nsExpatDriver::HandleError(const char *aBuffer, nsAutoString tagName; if (uriEnd && nameEnd) { - // We have a prefix. - tagName.Append(nameEnd + 1, pos - nameEnd - 1); - tagName.Append(PRUnichar(':')); + // We have a prefix. + tagName.Append(nameEnd + 1, pos - nameEnd - 1); + tagName.Append(PRUnichar(':')); } const PRUnichar *nameStart = uriEnd ? uriEnd + 1 : mismatch; tagName.Append(nameStart, (nameEnd ? nameEnd : pos) - nameStart); @@ -783,40 +781,29 @@ nsExpatDriver::HandleError(const char *aBuffer, nsTextFormatter::smprintf_free(message); } - nsAutoString sourceLine; - if (!aIsFinal) { - GetLine(aBuffer, aLength, - XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed, - sourceLine); - } - else { - sourceLine.Append(mLastLine); - } - // Adjust the column number so that it is one based rather than zero based. PRInt32 colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1; PRInt32 lineNumber = XML_GetCurrentLineNumber(mExpatParser); + nsAutoString errorText; + CreateErrorText(description.get(), XML_GetBase(mExpatParser), lineNumber, + colNumber, errorText); + + nsAutoString sourceText; + CreateSourceText(colNumber, mLastLine.get(), sourceText); + nsCOMPtr cs (do_GetService(NS_CONSOLESERVICE_CONTRACTID)); nsCOMPtr serr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); if (serr && cs) { if (NS_SUCCEEDED(serr->Init(description.get(), mURISpec.get(), - sourceLine.get(), + sourceText.get(), lineNumber, colNumber, nsIScriptError::errorFlag, "malformed-xml"))) cs->LogMessage(serr); } - nsAutoString errorText; - CreateErrorText(description.get(), XML_GetBase(mExpatParser), - XML_GetCurrentLineNumber(mExpatParser), colNumber, - errorText); - - nsAutoString sourceText; - CreateSourceText(colNumber, sourceLine.get(), sourceText); - NS_ASSERTION(mSink, "no sink?"); if (mSink) { mSink->ReportError(errorText.get(), sourceText.get()); @@ -831,27 +818,114 @@ nsExpatDriver::ParseBuffer(const char* aBuffer, PRBool aIsFinal) { NS_ASSERTION((aBuffer && aLength != 0) || (!aBuffer && aLength == 0), "?"); + NS_ASSERTION(aLength % sizeof(PRUnichar) == 0, + "We can have a PRUnichar spanning chunks?"); + NS_PRECONDITION(mBytesParsed % sizeof(PRUnichar) == 0, + "Parsed part of a PRUnichar?"); + NS_PRECONDITION(mBytePosition % sizeof(PRUnichar) == 0, + "Parsed part of a PRUnichar?"); + NS_PRECONDITION(XML_GetCurrentByteIndex(mExpatParser) == -1 || + XML_GetCurrentByteIndex(mExpatParser) % sizeof(PRUnichar) == 0, + "Consumed part of a PRUnichar?"); if (mExpatParser && mInternalState == NS_OK) { - if (!XML_Parse(mExpatParser, aBuffer, aLength, aIsFinal)) { - if (mInternalState == NS_ERROR_HTMLPARSER_BLOCK || - mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING) { - mBytePosition = (XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed); - mBytesParsed += mBytePosition; + XML_Bool parsedAll = XML_Parse(mExpatParser, aBuffer, aLength, aIsFinal); + + PRInt32 parserBytesConsumed = XML_GetCurrentByteIndex(mExpatParser); + + NS_ASSERTION(parserBytesConsumed == -1 || + parserBytesConsumed % sizeof(PRUnichar) == 0, + "Consumed part of a PRUnichar?"); + + // Now figure out the startOffset for appending to mLastLine -- this + // calculation is the same no matter whether we saw an error, got blocked, + // parsed it all but didn't consume it all, or whatever else happened. + const PRUnichar* const buffer = + NS_REINTERPRET_CAST(const PRUnichar*, aBuffer); + PRUint32 startOffset; + // we assume that if expat failed to consume some bytes last time it won't + // consume them this time without also consuming some bytes from aBuffer. + // Note that if expat consumed everything we passed it, it will have nulled + // out all its internal pointers to data, so parserBytesConsumed will come + // out -1 in that case. + if (buffer) { + if (parserBytesConsumed < 0 || + (PRUint32)parserBytesConsumed >= mBytesParsed) { + // We consumed something + if (parserBytesConsumed < 0) { + NS_ASSERTION(parserBytesConsumed == -1, + "Unexpected negative value?"); + // Consumed everything. + startOffset = aLength; + } + else { + // Consumed something, but not all + NS_ASSERTION(parserBytesConsumed - mBytesParsed <= aLength, + "Too many bytes consumed?"); + startOffset = (parserBytesConsumed - mBytesParsed) / + sizeof(PRUnichar); + } + // Now startOffset points one past the last PRUnichar consumed in + // buffer + while (startOffset-- != 0) { + if (buffer[startOffset] == '\n' || buffer[startOffset] == '\r') { + mLastLine.Truncate(); + break; + } + } + // Now startOffset is pointing to the last newline we consumed (or to + // -1 if there weren't any consumed in this chunk). Make startOffset + // point to the first char of the first line whose end we haven't + // consumed yet. + ++startOffset; } else { - HandleError(aBuffer, aLength, aIsFinal); + // Didn't parse anything new. So append all of aBuffer. + startOffset = 0; + } + } + + if (!parsedAll) { + if (mInternalState == NS_ERROR_HTMLPARSER_BLOCK || + mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING) { + NS_ASSERTION((PRUint32)parserBytesConsumed >= mBytesParsed, + "How'd this happen?"); + mBytePosition = parserBytesConsumed - mBytesParsed; + mBytesParsed = parserBytesConsumed; + if (buffer) { + PRUint32 endOffset = mBytePosition / sizeof(PRUnichar); + NS_ASSERTION(startOffset <= endOffset, + "Something is confused about what we've consumed"); + // Only append the data we actually parsed. The rest will come + // through this method again. + mLastLine.Append(Substring(buffer + startOffset, + buffer + endOffset)); + } + } + else { + // An error occured, look for the next newline after the last one we + // consumed. + PRUint32 length = aLength / sizeof(PRUnichar); + if (buffer) { + PRUint32 endOffset = startOffset; + while (endOffset < length && buffer[endOffset] != '\n' && + buffer[endOffset] != '\r') { + ++endOffset; + } + mLastLine.Append(Substring(buffer + startOffset, + buffer + endOffset)); + } + HandleError(); mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING; } return mInternalState; } - if (aBuffer && aLength != 0) { - // Cache the last line in the buffer - GetLine(aBuffer, aLength, aLength - sizeof(PRUnichar), mLastLine); + if (!aIsFinal && buffer) { + mLastLine.Append(Substring(buffer + startOffset, + buffer + aLength / sizeof(PRUnichar))); } - mBytesParsed += aLength; mBytePosition = 0; } @@ -859,76 +933,6 @@ nsExpatDriver::ParseBuffer(const char* aBuffer, return NS_OK; } -void -nsExpatDriver::GetLine(const char* aSourceBuffer, - PRUint32 aLength, - PRUint32 aOffset, - nsString& aLine) -{ - // Figure out the line inside aSourceBuffer that contains character specified - // by aOffset. Copy it into aLine. - NS_ASSERTION(aOffset < aLength, "?"); - // Assert that the byteIndex and the length of the buffer are even. - NS_ASSERTION(aOffset % 2 == 0 && aLength % 2 == 0, "?"); - - // Will try to find the start of the line. - PRUnichar* start = (PRUnichar*)&aSourceBuffer[aOffset]; - - // Will try to find the end of the line. - PRUnichar* end = (PRUnichar*)&aSourceBuffer[aOffset]; - - // Track the position of the 'start' pointer into the buffer. - PRUint32 startIndex = aOffset / sizeof(PRUnichar); - - // Track the position of the 'end' pointer into the buffer. - PRUint32 endIndex = aOffset / sizeof(PRUnichar); - - PRUint32 numCharsInBuffer = aLength / sizeof(PRUnichar); - - // Use start to find the first new line before the error position and end to - // find the first new line after the error position. - PRBool reachedStart = startIndex <= 0 || *start == '\n' || *start == '\r'; - PRBool reachedEnd = endIndex >= numCharsInBuffer || *end == '\n' || - *end == '\r'; - while (!reachedStart || !reachedEnd) { - if (!reachedStart) { - --start; - --startIndex; - reachedStart = startIndex <= 0 || *start == '\n' || *start == '\r'; - } - if (!reachedEnd) { - ++end; - ++endIndex; - reachedEnd = endIndex >= numCharsInBuffer || *end == '\n' || - *end == '\r'; - } - } - - aLine.Truncate(0); - if (startIndex == endIndex) { - // Special case if the error is on a line where the only character is a - // newline. Do nothing. - } - else { - NS_ASSERTION(endIndex - startIndex >= sizeof(PRUnichar), "?"); - // At this point, there are two cases. Either the error is on the first - // line or on subsequent lines. If the error is on the first line, - // startIndex will decrement all the way to zero. If not, startIndex - // will decrement to the position of the newline character on the - // previous line. So, in the first case, the start position of the - // error line = startIndex (== 0). In the second case, the start - // position of the error line = startIndex + 1. In both cases, the end - // position of the error line will be (endIndex - 1). - PRUint32 startPosn = startIndex <= 0 ? startIndex : startIndex + 1; - - // At this point the substring starting at startPosn and ending at - // (endIndex - 1) is the line on which the error occurred. Copy that - // substring into the error structure. - const PRUnichar* unicodeBuffer = (const PRUnichar*)aSourceBuffer; - aLine.Append(&unicodeBuffer[startPosn], endIndex - startPosn); - } -} - NS_IMETHODIMP nsExpatDriver::CreateNewInstance(nsIDTD** aInstancePtrResult) { @@ -958,8 +962,8 @@ nsExpatDriver::ConsumeToken(nsScanner& aScanner, if (NS_FAILED(mInternalState)) { if (mInternalState == NS_ERROR_HTMLPARSER_BLOCK) { - // mBytePosition / 2 => character position, one char is two bytes. - aScanner.SetPosition(start.advance(mBytePosition / 2), PR_TRUE); + aScanner.SetPosition(start.advance(mBytePosition / sizeof(PRUnichar)), + PR_TRUE); aScanner.Mark(); } diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.h b/mozilla/parser/htmlparser/src/nsExpatDriver.h index 2a29e7de31a..b4ca5367cd7 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.h +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.h @@ -91,7 +91,7 @@ private: nsAString& aAbsURL); nsresult ParseBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal); - nsresult HandleError(const char *aBuffer, PRUint32 aLength, PRBool aIsFinal); + nsresult HandleError(); void GetLine(const char* aSourceBuffer, PRUint32 aLength, PRUint32 aOffset, nsString& aLine); @@ -106,8 +106,12 @@ private: PRPackedBool mInCData; PRPackedBool mInInternalSubset; PRPackedBool mInExternalDTD; + + // Number of bytes parsed in the current buffer. PRInt32 mBytePosition; nsresult mInternalState; + + // Total number of bytes parsed. PRUint32 mBytesParsed; nsCOMPtr mSink; const nsCatalogData* mCatalogData; // weak