mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 10:33:33 +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 "nsElementTable.h"
|
||||
#include "nsParserService.h"
|
||||
#include "nsScanner.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#include "nsLoggingSink.h"
|
||||
@ -118,6 +119,8 @@ Shutdown(nsIModule* aSelf)
|
||||
DeleteElementTable();
|
||||
CNewlineToken::FreeNewline();
|
||||
gInitialized = PR_FALSE;
|
||||
delete nsScanner::gAllocator;
|
||||
nsScanner::gAllocator = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,48 @@
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
nsScannerString::nsScannerString(PRUnichar* aStorageStart,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd)
|
||||
nsRecyclingAllocator* nsScanner::gAllocator = nsnull;
|
||||
|
||||
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)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
PRUnichar* buffer = ToNewUnicode(anHTMLString);
|
||||
mTotalRead = anHTMLString.Length();
|
||||
InitAllocator();
|
||||
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;
|
||||
AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||
mMarkPosition = mCurrentPosition;
|
||||
mIncremental=PR_FALSE;
|
||||
mOwnsStream=PR_FALSE;
|
||||
mInputStream=0;
|
||||
@ -137,7 +179,7 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a
|
||||
mFilename(aFilename)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
InitAllocator();
|
||||
mSlidingBuffer = nsnull;
|
||||
mIncremental=PR_TRUE;
|
||||
mCountRemaining = 0;
|
||||
@ -166,7 +208,7 @@ nsScanner::nsScanner(const nsAString& aFilename,nsInputStream& aStream,const nsS
|
||||
mFilename(aFilename)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
InitAllocator();
|
||||
mSlidingBuffer = nsnull;
|
||||
mIncremental=PR_FALSE;
|
||||
mCountRemaining = 0;
|
||||
@ -262,8 +304,10 @@ nsScanner::~nsScanner() {
|
||||
* @return
|
||||
*/
|
||||
void nsScanner::RewindToMark(void){
|
||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||
mCurrentPosition = mMarkPosition;
|
||||
if (mSlidingBuffer) {
|
||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||
mCurrentPosition = mMarkPosition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -293,9 +337,15 @@ void nsScanner::Mark() {
|
||||
*/
|
||||
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||
|
||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
if (!mSlidingBuffer) {
|
||||
// This happens to be the first buffer. Just append it.
|
||||
AppendToBuffer(aBuffer);
|
||||
}
|
||||
else {
|
||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
}
|
||||
mTotalRead += aBuffer.Length();
|
||||
|
||||
return PR_TRUE;
|
||||
@ -309,12 +359,8 @@ PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||
* @return error code
|
||||
*/
|
||||
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
||||
|
||||
PRUnichar* buffer = ToNewUnicode(aBuffer);
|
||||
PRUint32 bufLen = aBuffer.Length();
|
||||
mTotalRead += bufLen;
|
||||
|
||||
AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen);
|
||||
AppendToBuffer(aBuffer);
|
||||
mTotalRead += aBuffer.Length();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -332,8 +378,8 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
||||
if(mUnicodeDecoder) {
|
||||
PRInt32 unicharBufLen = 0;
|
||||
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||
start = unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar));
|
||||
NS_ENSURE_TRUE(unichars,NS_ERROR_OUT_OF_MEMORY);
|
||||
start = unichars = (PRUnichar*) nsScannerAllocate((unicharBufLen+1) * sizeof(PRUnichar));
|
||||
NS_ENSURE_TRUE(unichars, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRInt32 totalChars = 0;
|
||||
PRInt32 unicharLength = unicharBufLen;
|
||||
@ -375,9 +421,7 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
||||
res = NS_OK;
|
||||
}
|
||||
else {
|
||||
nsDependentCString str(aBuffer, aLen);
|
||||
unichars = ToNewUnicode(str);
|
||||
AppendToBuffer(unichars, unichars+aLen, unichars+aLen);
|
||||
AppendToBuffer(aBuffer, aLen);
|
||||
mTotalRead+=aLen;
|
||||
}
|
||||
|
||||
@ -411,23 +455,18 @@ nsresult nsScanner::FillBuffer(void) {
|
||||
}
|
||||
else {
|
||||
PRInt32 numread=0;
|
||||
char* buf = new char[kBufsize+1];
|
||||
char buf[kBufsize+1];
|
||||
buf[kBufsize]=0;
|
||||
|
||||
if(mInputStream) {
|
||||
numread = mInputStream->read(buf, kBufsize);
|
||||
if (0 == numread) {
|
||||
delete [] buf;
|
||||
if (0 == numread)
|
||||
return kEOF;
|
||||
}
|
||||
}
|
||||
|
||||
if((0<numread) && (0==result)) {
|
||||
nsDependentCString str(buf, numread);
|
||||
PRUnichar* unichars = ToNewUnicode(str);
|
||||
AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1);
|
||||
AppendToBuffer(buf, numread);
|
||||
}
|
||||
delete [] buf;
|
||||
mTotalRead+=numread;
|
||||
}
|
||||
|
||||
@ -1359,11 +1398,13 @@ void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIte
|
||||
|
||||
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
||||
{
|
||||
NS_ASSERTION(mSlidingBuffer, "No data yet. CurrentPosition in invalid");
|
||||
aPosition = mCurrentPosition;
|
||||
}
|
||||
|
||||
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
||||
{
|
||||
NS_ASSERTION(mSlidingBuffer, "No data yet. EndPosition in invalid");
|
||||
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,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd)
|
||||
{
|
||||
if (!mSlidingBuffer) {
|
||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd);
|
||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd, nsScannerRecycle);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||
mMarkPosition = mCurrentPosition;
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
@ -1422,6 +1483,9 @@ void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
||||
* @return nada
|
||||
*/
|
||||
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
||||
if (!mSlidingBuffer)
|
||||
return;
|
||||
|
||||
nsReadingIterator<PRUnichar> start, end;
|
||||
start = mCurrentPosition;
|
||||
end = mEndPosition;
|
||||
|
@ -58,12 +58,17 @@
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsSlidingString.h"
|
||||
#include "nsRecyclingAllocator.h"
|
||||
|
||||
// Recycling memory used by scanner
|
||||
#define NS_SCANNER_BUCKETS 10
|
||||
|
||||
class nsScannerString : public nsSlidingString {
|
||||
public:
|
||||
nsScannerString(PRUnichar* aStorageStart,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd);
|
||||
PRUnichar* aStorageEnd,
|
||||
nsFreeProc* aFreeProc);
|
||||
|
||||
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
||||
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
||||
@ -382,6 +387,19 @@ class nsScanner {
|
||||
PRUnichar* aDataEnd,
|
||||
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;
|
||||
nsScannerString* mSlidingBuffer;
|
||||
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
||||
@ -397,6 +415,10 @@ class nsScanner {
|
||||
nsString mCharset;
|
||||
nsIUnicodeDecoder *mUnicodeDecoder;
|
||||
PRInt32 mNewlinesSkipped;
|
||||
|
||||
public:
|
||||
// Allocator to recycle memory used by scanner
|
||||
static nsRecyclingAllocator *gAllocator;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@
|
||||
//#include "nsTextTokenizer.h"
|
||||
#include "nsElementTable.h"
|
||||
#include "nsParserService.h"
|
||||
#include "nsScanner.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#include "nsLoggingSink.h"
|
||||
@ -118,6 +119,8 @@ Shutdown(nsIModule* aSelf)
|
||||
DeleteElementTable();
|
||||
CNewlineToken::FreeNewline();
|
||||
gInitialized = PR_FALSE;
|
||||
delete nsScanner::gAllocator;
|
||||
nsScanner::gAllocator = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,48 @@
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
nsScannerString::nsScannerString(PRUnichar* aStorageStart,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd)
|
||||
nsRecyclingAllocator* nsScanner::gAllocator = nsnull;
|
||||
|
||||
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)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
PRUnichar* buffer = ToNewUnicode(anHTMLString);
|
||||
mTotalRead = anHTMLString.Length();
|
||||
InitAllocator();
|
||||
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;
|
||||
AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||
mMarkPosition = mCurrentPosition;
|
||||
mIncremental=PR_FALSE;
|
||||
mOwnsStream=PR_FALSE;
|
||||
mInputStream=0;
|
||||
@ -137,7 +179,7 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a
|
||||
mFilename(aFilename)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
InitAllocator();
|
||||
mSlidingBuffer = nsnull;
|
||||
mIncremental=PR_TRUE;
|
||||
mCountRemaining = 0;
|
||||
@ -166,7 +208,7 @@ nsScanner::nsScanner(const nsAString& aFilename,nsInputStream& aStream,const nsS
|
||||
mFilename(aFilename)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsScanner);
|
||||
|
||||
InitAllocator();
|
||||
mSlidingBuffer = nsnull;
|
||||
mIncremental=PR_FALSE;
|
||||
mCountRemaining = 0;
|
||||
@ -262,8 +304,10 @@ nsScanner::~nsScanner() {
|
||||
* @return
|
||||
*/
|
||||
void nsScanner::RewindToMark(void){
|
||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||
mCurrentPosition = mMarkPosition;
|
||||
if (mSlidingBuffer) {
|
||||
mCountRemaining += (Distance(mMarkPosition, mCurrentPosition));
|
||||
mCurrentPosition = mMarkPosition;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -293,9 +337,15 @@ void nsScanner::Mark() {
|
||||
*/
|
||||
PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||
|
||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
if (!mSlidingBuffer) {
|
||||
// This happens to be the first buffer. Just append it.
|
||||
AppendToBuffer(aBuffer);
|
||||
}
|
||||
else {
|
||||
mSlidingBuffer->UngetReadable(aBuffer,mCurrentPosition);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition); // Insertion invalidated our iterators
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
}
|
||||
mTotalRead += aBuffer.Length();
|
||||
|
||||
return PR_TRUE;
|
||||
@ -309,12 +359,8 @@ PRBool nsScanner::UngetReadable(const nsAReadableString& aBuffer) {
|
||||
* @return error code
|
||||
*/
|
||||
nsresult nsScanner::Append(const nsAReadableString& aBuffer) {
|
||||
|
||||
PRUnichar* buffer = ToNewUnicode(aBuffer);
|
||||
PRUint32 bufLen = aBuffer.Length();
|
||||
mTotalRead += bufLen;
|
||||
|
||||
AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen);
|
||||
AppendToBuffer(aBuffer);
|
||||
mTotalRead += aBuffer.Length();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -332,8 +378,8 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
||||
if(mUnicodeDecoder) {
|
||||
PRInt32 unicharBufLen = 0;
|
||||
mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen);
|
||||
start = unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar));
|
||||
NS_ENSURE_TRUE(unichars,NS_ERROR_OUT_OF_MEMORY);
|
||||
start = unichars = (PRUnichar*) nsScannerAllocate((unicharBufLen+1) * sizeof(PRUnichar));
|
||||
NS_ENSURE_TRUE(unichars, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRInt32 totalChars = 0;
|
||||
PRInt32 unicharLength = unicharBufLen;
|
||||
@ -375,9 +421,7 @@ nsresult nsScanner::Append(const char* aBuffer, PRUint32 aLen){
|
||||
res = NS_OK;
|
||||
}
|
||||
else {
|
||||
nsDependentCString str(aBuffer, aLen);
|
||||
unichars = ToNewUnicode(str);
|
||||
AppendToBuffer(unichars, unichars+aLen, unichars+aLen);
|
||||
AppendToBuffer(aBuffer, aLen);
|
||||
mTotalRead+=aLen;
|
||||
}
|
||||
|
||||
@ -411,23 +455,18 @@ nsresult nsScanner::FillBuffer(void) {
|
||||
}
|
||||
else {
|
||||
PRInt32 numread=0;
|
||||
char* buf = new char[kBufsize+1];
|
||||
char buf[kBufsize+1];
|
||||
buf[kBufsize]=0;
|
||||
|
||||
if(mInputStream) {
|
||||
numread = mInputStream->read(buf, kBufsize);
|
||||
if (0 == numread) {
|
||||
delete [] buf;
|
||||
if (0 == numread)
|
||||
return kEOF;
|
||||
}
|
||||
}
|
||||
|
||||
if((0<numread) && (0==result)) {
|
||||
nsDependentCString str(buf, numread);
|
||||
PRUnichar* unichars = ToNewUnicode(str);
|
||||
AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1);
|
||||
AppendToBuffer(buf, numread);
|
||||
}
|
||||
delete [] buf;
|
||||
mTotalRead+=numread;
|
||||
}
|
||||
|
||||
@ -1359,11 +1398,13 @@ void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIte
|
||||
|
||||
void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition)
|
||||
{
|
||||
NS_ASSERTION(mSlidingBuffer, "No data yet. CurrentPosition in invalid");
|
||||
aPosition = mCurrentPosition;
|
||||
}
|
||||
|
||||
void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition)
|
||||
{
|
||||
NS_ASSERTION(mSlidingBuffer, "No data yet. EndPosition in invalid");
|
||||
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,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd)
|
||||
{
|
||||
if (!mSlidingBuffer) {
|
||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd);
|
||||
mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd, nsScannerRecycle);
|
||||
mSlidingBuffer->BeginReading(mCurrentPosition);
|
||||
mMarkPosition = mCurrentPosition;
|
||||
mSlidingBuffer->EndReading(mEndPosition);
|
||||
@ -1422,6 +1483,9 @@ void nsScanner::AppendToBuffer(PRUnichar* aStorageStart,
|
||||
* @return nada
|
||||
*/
|
||||
void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
|
||||
if (!mSlidingBuffer)
|
||||
return;
|
||||
|
||||
nsReadingIterator<PRUnichar> start, end;
|
||||
start = mCurrentPosition;
|
||||
end = mEndPosition;
|
||||
|
@ -58,12 +58,17 @@
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsSlidingString.h"
|
||||
#include "nsRecyclingAllocator.h"
|
||||
|
||||
// Recycling memory used by scanner
|
||||
#define NS_SCANNER_BUCKETS 10
|
||||
|
||||
class nsScannerString : public nsSlidingString {
|
||||
public:
|
||||
nsScannerString(PRUnichar* aStorageStart,
|
||||
PRUnichar* aDataEnd,
|
||||
PRUnichar* aStorageEnd);
|
||||
PRUnichar* aStorageEnd,
|
||||
nsFreeProc* aFreeProc);
|
||||
|
||||
virtual void UngetReadable(const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aCurrentPosition) { InsertReadable(aReadable,aCurrentPosition); }
|
||||
virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition,
|
||||
@ -382,6 +387,19 @@ class nsScanner {
|
||||
PRUnichar* aDataEnd,
|
||||
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;
|
||||
nsScannerString* mSlidingBuffer;
|
||||
nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer
|
||||
@ -397,6 +415,10 @@ class nsScanner {
|
||||
nsString mCharset;
|
||||
nsIUnicodeDecoder *mUnicodeDecoder;
|
||||
PRInt32 mNewlinesSkipped;
|
||||
|
||||
public:
|
||||
// Allocator to recycle memory used by scanner
|
||||
static nsRecyclingAllocator *gAllocator;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user