mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
(again) bug 116023 Parser recycling buffers. Protects all cases of
usage of mCurrentPosition without checking mSlidingBuffer. r=harishd, sr=sfraser, a=asa
This commit is contained in:
parent
74a917c925
commit
6164595e54
@ -53,6 +53,7 @@
|
|||||||
//#include "nsTextTokenizer.h"
|
//#include "nsTextTokenizer.h"
|
||||||
#include "nsElementTable.h"
|
#include "nsElementTable.h"
|
||||||
#include "nsParserService.h"
|
#include "nsParserService.h"
|
||||||
|
#include "nsScanner.h"
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
#include "nsLoggingSink.h"
|
#include "nsLoggingSink.h"
|
||||||
@ -118,6 +119,8 @@ Shutdown(nsIModule* aSelf)
|
|||||||
DeleteElementTable();
|
DeleteElementTable();
|
||||||
CNewlineToken::FreeNewline();
|
CNewlineToken::FreeNewline();
|
||||||
gInitialized = PR_FALSE;
|
gInitialized = PR_FALSE;
|
||||||
|
delete nsScanner::gAllocator;
|
||||||
|
nsScanner::gAllocator = nsnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +46,48 @@
|
|||||||
#include "nsFileSpec.h"
|
#include "nsFileSpec.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
|
|
||||||
nsScannerString::nsScannerString(PRUnichar* aStorageStart,
|
nsRecyclingAllocator* nsScanner::gAllocator = nsnull;
|
||||||
PRUnichar* aDataEnd,
|
|
||||||
PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd)
|
static void nsScannerRecycle(void *aPtr, void *aClientData)
|
||||||
|
{
|
||||||
|
nsScanner::gAllocator->Free(aPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *nsScannerAllocate(PRUint32 size)
|
||||||
|
{
|
||||||
|
return nsScanner::gAllocator->Malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper funciton to convert raw 8bit char * to unicode
|
||||||
|
*
|
||||||
|
* aStr : input 8bit string
|
||||||
|
* aLen : length of input string aStr
|
||||||
|
* aDest : Destination unicode buffer. Null terminated.
|
||||||
|
* aDestLength : size of destination buffer. Must be atleast aLen+1.
|
||||||
|
*
|
||||||
|
* return 0 if conversion succeeded
|
||||||
|
* returns -1, if there is not enough space in destination buffer,
|
||||||
|
*/
|
||||||
|
static int RawToUnicode(const char *aStr, PRInt32 aLen, PRUnichar *aDest, PRUint32 aDestLength)
|
||||||
|
{
|
||||||
|
// Alert if someone if passing null buffers to us
|
||||||
|
NS_ASSERTION(aStr && aDest, "Null buffers");
|
||||||
|
|
||||||
|
// Error checking
|
||||||
|
if (!aStr || !aDest || (PRInt32)aDestLength < aLen+1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (*aStr)
|
||||||
|
*aDest++ = (PRUnichar) (unsigned char) *aStr++;
|
||||||
|
*aDest = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsScannerString::nsScannerString(PRUnichar* aStorageStart, PRUnichar* aDataEnd,
|
||||||
|
PRUnichar* aStorageEnd, nsFreeProc *aFreeProc)
|
||||||
|
: nsSlidingString(aStorageStart, aDataEnd, aStorageEnd, aFreeProc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,14 +146,17 @@ MOZ_DECL_CTOR_COUNTER(nsScanner)
|
|||||||
nsScanner::nsScanner(const nsAString& anHTMLString, const nsString& aCharset, PRInt32 aSource)
|
nsScanner::nsScanner(const nsAString& anHTMLString, const nsString& aCharset, PRInt32 aSource)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
PRUnichar* buffer = ToNewUnicode(anHTMLString);
|
|
||||||
mTotalRead = anHTMLString.Length();
|
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
|
mTotalRead = anHTMLString.Length();
|
||||||
|
if (mTotalRead) {
|
||||||
|
// Append to buffer will take care of initializing mCurrentPosition
|
||||||
|
// and mMarkPosition. If we didnt get here, mCurrentPosition and
|
||||||
|
// mMarkPosition would be uninitialized and hence we protect using these
|
||||||
|
// variables with if (mSlidingBuffer) checks all over the code.
|
||||||
|
AppendToBuffer(anHTMLString);
|
||||||
|
}
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead);
|
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
|
||||||
mMarkPosition = mCurrentPosition;
|
|
||||||
mIncremental=PR_FALSE;
|
mIncremental=PR_FALSE;
|
||||||
mOwnsStream=PR_FALSE;
|
mOwnsStream=PR_FALSE;
|
||||||
mInputStream=0;
|
mInputStream=0;
|
||||||
@ -137,7 +179,7 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a
|
|||||||
mFilename(aFilename)
|
mFilename(aFilename)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
mIncremental=PR_TRUE;
|
mIncremental=PR_TRUE;
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
@ -166,7 +208,7 @@ nsScanner::nsScanner(const nsAString& aFilename,nsInputStream& aStream,const nsS
|
|||||||
mFilename(aFilename)
|
mFilename(aFilename)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
mIncremental=PR_FALSE;
|
mIncremental=PR_FALSE;
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
@ -262,8 +304,10 @@ nsScanner::~nsScanner() {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void nsScanner::RewindToMark(void){
|
void nsScanner::RewindToMark(void){
|
||||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
if (mSlidingBuffer) {
|
||||||
mCurrentPosition = mMarkPosition;
|
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||||
|
mCurrentPosition = mMarkPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -293,9 +337,15 @@ void nsScanner::Mark() {
|
|||||||
*/
|
*/
|
||||||
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||||
|
|
||||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
if (!mSlidingBuffer) {
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
// This happens to be the first buffer. Just append it.
|
||||||
mSlidingBuffer->EndReading(mEndPosition);
|
AppendToBuffer(aBuffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||||
|
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||||
|
mSlidingBuffer->EndReading(mEndPosition);
|
||||||
|
}
|
||||||
mTotalRead += aBuffer.Length();
|
mTotalRead += aBuffer.Length();
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
@ -309,12 +359,8 @@ PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
|||||||
* @return error code
|
* @return error code
|
||||||
*/
|
*/
|
||||||
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
||||||
|
AppendToBuffer(aBuffer);
|
||||||
PRUnichar* buffer = ToNewUnicode(aBuffer);
|
mTotalRead += aBuffer.Length();
|
||||||
PRUint32 bufLen = aBuffer.Length();
|
|
||||||
mTotalRead += bufLen;
|
|
||||||
|
|
||||||
AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -332,8 +378,8 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
|||||||
if(mUnicodeDecoder) {
|
if(mUnicodeDecoder) {
|
||||||
PRInt32 unicharBufLen = 0;
|
PRInt32 unicharBufLen = 0;
|
||||||
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||||
start = unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar));
|
start = unichars = (PRUnichar*) nsScannerAllocate((unicharBufLen+1) * sizeof(PRUnichar));
|
||||||
NS_ENSURE_TRUE(unichars,NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(unichars, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
PRInt32 totalChars = 0;
|
PRInt32 totalChars = 0;
|
||||||
PRInt32 unicharLength = unicharBufLen;
|
PRInt32 unicharLength = unicharBufLen;
|
||||||
@ -375,9 +421,7 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
|||||||
res = NS_OK;
|
res = NS_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nsDependentCString str(aBuffer, aLen);
|
AppendToBuffer(aBuffer, aLen);
|
||||||
unichars = ToNewUnicode(str);
|
|
||||||
AppendToBuffer(unichars, unichars+aLen, unichars+aLen);
|
|
||||||
mTotalRead+=aLen;
|
mTotalRead+=aLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,23 +455,18 @@ nsresult nsScanner::FillBuffer(void) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PRInt32 numread=0;
|
PRInt32 numread=0;
|
||||||
char* buf = new char[kBufsize+1];
|
char buf[kBufsize+1];
|
||||||
buf[kBufsize]=0;
|
buf[kBufsize]=0;
|
||||||
|
|
||||||
if(mInputStream) {
|
if(mInputStream) {
|
||||||
numread = mInputStream->read(buf, kBufsize);
|
numread = mInputStream->read(buf, kBufsize);
|
||||||
if (0 == numread) {
|
if (0 == numread)
|
||||||
delete [] buf;
|
|
||||||
return kEOF;
|
return kEOF;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((0<numread) && (0==result)) {
|
if((0<numread) && (0==result)) {
|
||||||
nsDependentCString str(buf, numread);
|
AppendToBuffer(buf, numread);
|
||||||
PRUnichar* unichars = ToNewUnicode(str);
|
|
||||||
AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1);
|
|
||||||
}
|
}
|
||||||
delete [] buf;
|
|
||||||
mTotalRead+=numread;
|
mTotalRead+=numread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,11 +1398,13 @@ void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIte
|
|||||||
|
|
||||||
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(mSlidingBuffer, "No data yet. CurrentPosition in invalid");
|
||||||
aPosition = mCurrentPosition;
|
aPosition = mCurrentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(mSlidingBuffer, "No data yet. EndPosition in invalid");
|
||||||
aPosition = mEndPosition;
|
aPosition = mEndPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1392,12 +1433,32 @@ void nsScanner::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsScanner::AppendToBuffer(const nsAString &aData)
|
||||||
|
{
|
||||||
|
PRUint32 len = aData.Length();
|
||||||
|
PRUnichar* buffer = (PRUnichar *) nsScannerAllocate(len * sizeof(PRUnichar));
|
||||||
|
if (buffer) {
|
||||||
|
CopyUnicodeTo(aData, 0, buffer, len);
|
||||||
|
AppendToBuffer(buffer, buffer+len, buffer+len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsScanner::AppendToBuffer(const char *aData, PRUint32 aLen)
|
||||||
|
{
|
||||||
|
PRUnichar *buffer = (PRUnichar*) nsScannerAllocate((aLen+1) * sizeof(PRUnichar));
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
RawToUnicode(aData, aLen, buffer, aLen+1);
|
||||||
|
AppendToBuffer(buffer, buffer+aLen, buffer+aLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd)
|
PRUnichar* aStorageEnd)
|
||||||
{
|
{
|
||||||
if (!mSlidingBuffer) {
|
if (!mSlidingBuffer) {
|
||||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd);
|
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd, nsScannerRecycle);
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||||
mMarkPosition = mCurrentPosition;
|
mMarkPosition = mCurrentPosition;
|
||||||
mSlidingBuffer->EndReading(mEndPosition);
|
mSlidingBuffer->EndReading(mEndPosition);
|
||||||
@ -1422,6 +1483,9 @@ void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
|||||||
* @return nada
|
* @return nada
|
||||||
*/
|
*/
|
||||||
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
||||||
|
if (!mSlidingBuffer)
|
||||||
|
return;
|
||||||
|
|
||||||
nsReadingIterator<PRUnichar> start, end;
|
nsReadingIterator<PRUnichar> start, end;
|
||||||
start = mCurrentPosition;
|
start = mCurrentPosition;
|
||||||
end = mEndPosition;
|
end = mEndPosition;
|
||||||
|
@ -58,12 +58,17 @@
|
|||||||
#include "nsIUnicodeDecoder.h"
|
#include "nsIUnicodeDecoder.h"
|
||||||
#include "nsFileStream.h"
|
#include "nsFileStream.h"
|
||||||
#include "nsSlidingString.h"
|
#include "nsSlidingString.h"
|
||||||
|
#include "nsRecyclingAllocator.h"
|
||||||
|
|
||||||
|
// Recycling memory used by scanner
|
||||||
|
#define NS_SCANNER_BUCKETS 10
|
||||||
|
|
||||||
class nsScannerString : public nsSlidingString {
|
class nsScannerString : public nsSlidingString {
|
||||||
public:
|
public:
|
||||||
nsScannerString(PRUnichar* aStorageStart,
|
nsScannerString(PRUnichar* aStorageStart,
|
||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd);
|
PRUnichar* aStorageEnd,
|
||||||
|
nsFreeProc* aFreeProc);
|
||||||
|
|
||||||
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
||||||
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
||||||
@ -382,6 +387,19 @@ class nsScanner {
|
|||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd);
|
PRUnichar* aStorageEnd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These versions of AppendToBuffer allocate from the recyclingallocator,
|
||||||
|
* convert to unicode if necessary and then add the buffer into the sliding
|
||||||
|
* string
|
||||||
|
*/
|
||||||
|
void AppendToBuffer(const nsAString &aData);
|
||||||
|
void AppendToBuffer(const char* aData, PRUint32 aLen);
|
||||||
|
|
||||||
|
static void InitAllocator() {
|
||||||
|
if (!gAllocator)
|
||||||
|
gAllocator = new nsRecyclingAllocator(NS_SCANNER_BUCKETS, NS_DEFAULT_RECYCLE_TIMEOUT, "parser");
|
||||||
|
}
|
||||||
|
|
||||||
nsInputStream* mInputStream;
|
nsInputStream* mInputStream;
|
||||||
nsScannerString* mSlidingBuffer;
|
nsScannerString* mSlidingBuffer;
|
||||||
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
||||||
@ -397,6 +415,10 @@ class nsScanner {
|
|||||||
nsString mCharset;
|
nsString mCharset;
|
||||||
nsIUnicodeDecoder *mUnicodeDecoder;
|
nsIUnicodeDecoder *mUnicodeDecoder;
|
||||||
PRInt32 mNewlinesSkipped;
|
PRInt32 mNewlinesSkipped;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Allocator to recycle memory used by scanner
|
||||||
|
static nsRecyclingAllocator *gAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
//#include "nsTextTokenizer.h"
|
//#include "nsTextTokenizer.h"
|
||||||
#include "nsElementTable.h"
|
#include "nsElementTable.h"
|
||||||
#include "nsParserService.h"
|
#include "nsParserService.h"
|
||||||
|
#include "nsScanner.h"
|
||||||
|
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
#include "nsLoggingSink.h"
|
#include "nsLoggingSink.h"
|
||||||
@ -118,6 +119,8 @@ Shutdown(nsIModule* aSelf)
|
|||||||
DeleteElementTable();
|
DeleteElementTable();
|
||||||
CNewlineToken::FreeNewline();
|
CNewlineToken::FreeNewline();
|
||||||
gInitialized = PR_FALSE;
|
gInitialized = PR_FALSE;
|
||||||
|
delete nsScanner::gAllocator;
|
||||||
|
nsScanner::gAllocator = nsnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +46,48 @@
|
|||||||
#include "nsFileSpec.h"
|
#include "nsFileSpec.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
|
|
||||||
nsScannerString::nsScannerString(PRUnichar* aStorageStart,
|
nsRecyclingAllocator* nsScanner::gAllocator = nsnull;
|
||||||
PRUnichar* aDataEnd,
|
|
||||||
PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd)
|
static void nsScannerRecycle(void *aPtr, void *aClientData)
|
||||||
|
{
|
||||||
|
nsScanner::gAllocator->Free(aPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *nsScannerAllocate(PRUint32 size)
|
||||||
|
{
|
||||||
|
return nsScanner::gAllocator->Malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper funciton to convert raw 8bit char * to unicode
|
||||||
|
*
|
||||||
|
* aStr : input 8bit string
|
||||||
|
* aLen : length of input string aStr
|
||||||
|
* aDest : Destination unicode buffer. Null terminated.
|
||||||
|
* aDestLength : size of destination buffer. Must be atleast aLen+1.
|
||||||
|
*
|
||||||
|
* return 0 if conversion succeeded
|
||||||
|
* returns -1, if there is not enough space in destination buffer,
|
||||||
|
*/
|
||||||
|
static int RawToUnicode(const char *aStr, PRInt32 aLen, PRUnichar *aDest, PRUint32 aDestLength)
|
||||||
|
{
|
||||||
|
// Alert if someone if passing null buffers to us
|
||||||
|
NS_ASSERTION(aStr && aDest, "Null buffers");
|
||||||
|
|
||||||
|
// Error checking
|
||||||
|
if (!aStr || !aDest || (PRInt32)aDestLength < aLen+1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (*aStr)
|
||||||
|
*aDest++ = (PRUnichar) (unsigned char) *aStr++;
|
||||||
|
*aDest = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsScannerString::nsScannerString(PRUnichar* aStorageStart, PRUnichar* aDataEnd,
|
||||||
|
PRUnichar* aStorageEnd, nsFreeProc *aFreeProc)
|
||||||
|
: nsSlidingString(aStorageStart, aDataEnd, aStorageEnd, aFreeProc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,14 +146,17 @@ MOZ_DECL_CTOR_COUNTER(nsScanner)
|
|||||||
nsScanner::nsScanner(const nsAString& anHTMLString, const nsString& aCharset, PRInt32 aSource)
|
nsScanner::nsScanner(const nsAString& anHTMLString, const nsString& aCharset, PRInt32 aSource)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
PRUnichar* buffer = ToNewUnicode(anHTMLString);
|
|
||||||
mTotalRead = anHTMLString.Length();
|
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
|
mTotalRead = anHTMLString.Length();
|
||||||
|
if (mTotalRead) {
|
||||||
|
// Append to buffer will take care of initializing mCurrentPosition
|
||||||
|
// and mMarkPosition. If we didnt get here, mCurrentPosition and
|
||||||
|
// mMarkPosition would be uninitialized and hence we protect using these
|
||||||
|
// variables with if (mSlidingBuffer) checks all over the code.
|
||||||
|
AppendToBuffer(anHTMLString);
|
||||||
|
}
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead);
|
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
|
||||||
mMarkPosition = mCurrentPosition;
|
|
||||||
mIncremental=PR_FALSE;
|
mIncremental=PR_FALSE;
|
||||||
mOwnsStream=PR_FALSE;
|
mOwnsStream=PR_FALSE;
|
||||||
mInputStream=0;
|
mInputStream=0;
|
||||||
@ -137,7 +179,7 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a
|
|||||||
mFilename(aFilename)
|
mFilename(aFilename)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
mIncremental=PR_TRUE;
|
mIncremental=PR_TRUE;
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
@ -166,7 +208,7 @@ nsScanner::nsScanner(const nsAString& aFilename,nsInputStream& aStream,const nsS
|
|||||||
mFilename(aFilename)
|
mFilename(aFilename)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsScanner);
|
MOZ_COUNT_CTOR(nsScanner);
|
||||||
|
InitAllocator();
|
||||||
mSlidingBuffer = nsnull;
|
mSlidingBuffer = nsnull;
|
||||||
mIncremental=PR_FALSE;
|
mIncremental=PR_FALSE;
|
||||||
mCountRemaining = 0;
|
mCountRemaining = 0;
|
||||||
@ -262,8 +304,10 @@ nsScanner::~nsScanner() {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void nsScanner::RewindToMark(void){
|
void nsScanner::RewindToMark(void){
|
||||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
if (mSlidingBuffer) {
|
||||||
mCurrentPosition = mMarkPosition;
|
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||||
|
mCurrentPosition = mMarkPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -293,9 +337,15 @@ void nsScanner::Mark() {
|
|||||||
*/
|
*/
|
||||||
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||||
|
|
||||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
if (!mSlidingBuffer) {
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
// This happens to be the first buffer. Just append it.
|
||||||
mSlidingBuffer->EndReading(mEndPosition);
|
AppendToBuffer(aBuffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||||
|
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||||
|
mSlidingBuffer->EndReading(mEndPosition);
|
||||||
|
}
|
||||||
mTotalRead += aBuffer.Length();
|
mTotalRead += aBuffer.Length();
|
||||||
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
@ -309,12 +359,8 @@ PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
|||||||
* @return error code
|
* @return error code
|
||||||
*/
|
*/
|
||||||
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
||||||
|
AppendToBuffer(aBuffer);
|
||||||
PRUnichar* buffer = ToNewUnicode(aBuffer);
|
mTotalRead += aBuffer.Length();
|
||||||
PRUint32 bufLen = aBuffer.Length();
|
|
||||||
mTotalRead += bufLen;
|
|
||||||
|
|
||||||
AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -332,8 +378,8 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
|||||||
if(mUnicodeDecoder) {
|
if(mUnicodeDecoder) {
|
||||||
PRInt32 unicharBufLen = 0;
|
PRInt32 unicharBufLen = 0;
|
||||||
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||||
start = unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar));
|
start = unichars = (PRUnichar*) nsScannerAllocate((unicharBufLen+1) * sizeof(PRUnichar));
|
||||||
NS_ENSURE_TRUE(unichars,NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(unichars, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
PRInt32 totalChars = 0;
|
PRInt32 totalChars = 0;
|
||||||
PRInt32 unicharLength = unicharBufLen;
|
PRInt32 unicharLength = unicharBufLen;
|
||||||
@ -375,9 +421,7 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
|||||||
res = NS_OK;
|
res = NS_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nsDependentCString str(aBuffer, aLen);
|
AppendToBuffer(aBuffer, aLen);
|
||||||
unichars = ToNewUnicode(str);
|
|
||||||
AppendToBuffer(unichars, unichars+aLen, unichars+aLen);
|
|
||||||
mTotalRead+=aLen;
|
mTotalRead+=aLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,23 +455,18 @@ nsresult nsScanner::FillBuffer(void) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PRInt32 numread=0;
|
PRInt32 numread=0;
|
||||||
char* buf = new char[kBufsize+1];
|
char buf[kBufsize+1];
|
||||||
buf[kBufsize]=0;
|
buf[kBufsize]=0;
|
||||||
|
|
||||||
if(mInputStream) {
|
if(mInputStream) {
|
||||||
numread = mInputStream->read(buf, kBufsize);
|
numread = mInputStream->read(buf, kBufsize);
|
||||||
if (0 == numread) {
|
if (0 == numread)
|
||||||
delete [] buf;
|
|
||||||
return kEOF;
|
return kEOF;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((0<numread) && (0==result)) {
|
if((0<numread) && (0==result)) {
|
||||||
nsDependentCString str(buf, numread);
|
AppendToBuffer(buf, numread);
|
||||||
PRUnichar* unichars = ToNewUnicode(str);
|
|
||||||
AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1);
|
|
||||||
}
|
}
|
||||||
delete [] buf;
|
|
||||||
mTotalRead+=numread;
|
mTotalRead+=numread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,11 +1398,13 @@ void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIte
|
|||||||
|
|
||||||
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(mSlidingBuffer, "No data yet. CurrentPosition in invalid");
|
||||||
aPosition = mCurrentPosition;
|
aPosition = mCurrentPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
||||||
{
|
{
|
||||||
|
NS_ASSERTION(mSlidingBuffer, "No data yet. EndPosition in invalid");
|
||||||
aPosition = mEndPosition;
|
aPosition = mEndPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1392,12 +1433,32 @@ void nsScanner::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsScanner::AppendToBuffer(const nsAString &aData)
|
||||||
|
{
|
||||||
|
PRUint32 len = aData.Length();
|
||||||
|
PRUnichar* buffer = (PRUnichar *) nsScannerAllocate(len * sizeof(PRUnichar));
|
||||||
|
if (buffer) {
|
||||||
|
CopyUnicodeTo(aData, 0, buffer, len);
|
||||||
|
AppendToBuffer(buffer, buffer+len, buffer+len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsScanner::AppendToBuffer(const char *aData, PRUint32 aLen)
|
||||||
|
{
|
||||||
|
PRUnichar *buffer = (PRUnichar*) nsScannerAllocate((aLen+1) * sizeof(PRUnichar));
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
RawToUnicode(aData, aLen, buffer, aLen+1);
|
||||||
|
AppendToBuffer(buffer, buffer+aLen, buffer+aLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd)
|
PRUnichar* aStorageEnd)
|
||||||
{
|
{
|
||||||
if (!mSlidingBuffer) {
|
if (!mSlidingBuffer) {
|
||||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd);
|
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd, nsScannerRecycle);
|
||||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||||
mMarkPosition = mCurrentPosition;
|
mMarkPosition = mCurrentPosition;
|
||||||
mSlidingBuffer->EndReading(mEndPosition);
|
mSlidingBuffer->EndReading(mEndPosition);
|
||||||
@ -1422,6 +1483,9 @@ void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
|||||||
* @return nada
|
* @return nada
|
||||||
*/
|
*/
|
||||||
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
||||||
|
if (!mSlidingBuffer)
|
||||||
|
return;
|
||||||
|
|
||||||
nsReadingIterator<PRUnichar> start, end;
|
nsReadingIterator<PRUnichar> start, end;
|
||||||
start = mCurrentPosition;
|
start = mCurrentPosition;
|
||||||
end = mEndPosition;
|
end = mEndPosition;
|
||||||
|
@ -58,12 +58,17 @@
|
|||||||
#include "nsIUnicodeDecoder.h"
|
#include "nsIUnicodeDecoder.h"
|
||||||
#include "nsFileStream.h"
|
#include "nsFileStream.h"
|
||||||
#include "nsSlidingString.h"
|
#include "nsSlidingString.h"
|
||||||
|
#include "nsRecyclingAllocator.h"
|
||||||
|
|
||||||
|
// Recycling memory used by scanner
|
||||||
|
#define NS_SCANNER_BUCKETS 10
|
||||||
|
|
||||||
class nsScannerString : public nsSlidingString {
|
class nsScannerString : public nsSlidingString {
|
||||||
public:
|
public:
|
||||||
nsScannerString(PRUnichar* aStorageStart,
|
nsScannerString(PRUnichar* aStorageStart,
|
||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd);
|
PRUnichar* aStorageEnd,
|
||||||
|
nsFreeProc* aFreeProc);
|
||||||
|
|
||||||
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
||||||
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
||||||
@ -382,6 +387,19 @@ class nsScanner {
|
|||||||
PRUnichar* aDataEnd,
|
PRUnichar* aDataEnd,
|
||||||
PRUnichar* aStorageEnd);
|
PRUnichar* aStorageEnd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These versions of AppendToBuffer allocate from the recyclingallocator,
|
||||||
|
* convert to unicode if necessary and then add the buffer into the sliding
|
||||||
|
* string
|
||||||
|
*/
|
||||||
|
void AppendToBuffer(const nsAString &aData);
|
||||||
|
void AppendToBuffer(const char* aData, PRUint32 aLen);
|
||||||
|
|
||||||
|
static void InitAllocator() {
|
||||||
|
if (!gAllocator)
|
||||||
|
gAllocator = new nsRecyclingAllocator(NS_SCANNER_BUCKETS, NS_DEFAULT_RECYCLE_TIMEOUT, "parser");
|
||||||
|
}
|
||||||
|
|
||||||
nsInputStream* mInputStream;
|
nsInputStream* mInputStream;
|
||||||
nsScannerString* mSlidingBuffer;
|
nsScannerString* mSlidingBuffer;
|
||||||
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
||||||
@ -397,6 +415,10 @@ class nsScanner {
|
|||||||
nsString mCharset;
|
nsString mCharset;
|
||||||
nsIUnicodeDecoder *mUnicodeDecoder;
|
nsIUnicodeDecoder *mUnicodeDecoder;
|
||||||
PRInt32 mNewlinesSkipped;
|
PRInt32 mNewlinesSkipped;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Allocator to recycle memory used by scanner
|
||||||
|
static nsRecyclingAllocator *gAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user