diff --git a/htmlparser/src/nsScanner.cpp b/htmlparser/src/nsScanner.cpp index 0c39b551718..0995b272396 100644 --- a/htmlparser/src/nsScanner.cpp +++ b/htmlparser/src/nsScanner.cpp @@ -38,13 +38,25 @@ nsScannerString::nsScannerString(PRUnichar* aStorageStart, } void -nsScannerString::InsertBuffer(PRUnichar* aStorageStart, - PRUnichar* aDataEnd, - PRUnichar* aStorageEnd) +nsScannerString::InsertData(const PRUnichar* aDataStart, + const PRUnichar* aDataEnd) + /* + * Warning: this routine manipulates the shared buffer list in an unexpected way. + * The original design did not really allow for insertions, but this call promises + * that if called for a point after then end of all extant token strings, that no token string + * nor the work string will be invalidated. + */ { - // XXX This is where insertion of a buffer at the head - // of the buffer list will take place pending checkins - // from scc. + mBufferList->SplitBuffer(mStart, nsSharedBufferList::kSplitCopyRightData); + // splitting to the right keeps the work string and any extant token pointing to and + // holding a reference count on the same buffer + + Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(aDataStart, aDataEnd-aDataStart, 0); + // make a new buffer with all the data to insert... + // BULLSHIT ALERT: we may have empty space to re-use in the split buffer, measure the cost + // of this and decide if we should do the work to fill it + + mBufferList->LinkBuffer(mStart.mBuffer, new_buffer, mStart.mBuffer->mNext); } void diff --git a/htmlparser/src/nsScanner.h b/htmlparser/src/nsScanner.h index e904af37b25..28078699072 100644 --- a/htmlparser/src/nsScanner.h +++ b/htmlparser/src/nsScanner.h @@ -48,9 +48,8 @@ class nsScannerString : public nsSlidingString { nsScannerString(PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd); - virtual void InsertBuffer(PRUnichar* aStorageStart, - PRUnichar* aDataEnd, - PRUnichar* aStorageEnd); + virtual void InsertData(const PRUnichar* aDataStart, + const PRUnichar* aDataEnd); virtual void ReplaceCharacter(nsReadingIterator& aPosition, PRUnichar aChar); }; diff --git a/parser/htmlparser/src/nsScanner.cpp b/parser/htmlparser/src/nsScanner.cpp index 0c39b551718..0995b272396 100644 --- a/parser/htmlparser/src/nsScanner.cpp +++ b/parser/htmlparser/src/nsScanner.cpp @@ -38,13 +38,25 @@ nsScannerString::nsScannerString(PRUnichar* aStorageStart, } void -nsScannerString::InsertBuffer(PRUnichar* aStorageStart, - PRUnichar* aDataEnd, - PRUnichar* aStorageEnd) +nsScannerString::InsertData(const PRUnichar* aDataStart, + const PRUnichar* aDataEnd) + /* + * Warning: this routine manipulates the shared buffer list in an unexpected way. + * The original design did not really allow for insertions, but this call promises + * that if called for a point after then end of all extant token strings, that no token string + * nor the work string will be invalidated. + */ { - // XXX This is where insertion of a buffer at the head - // of the buffer list will take place pending checkins - // from scc. + mBufferList->SplitBuffer(mStart, nsSharedBufferList::kSplitCopyRightData); + // splitting to the right keeps the work string and any extant token pointing to and + // holding a reference count on the same buffer + + Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(aDataStart, aDataEnd-aDataStart, 0); + // make a new buffer with all the data to insert... + // BULLSHIT ALERT: we may have empty space to re-use in the split buffer, measure the cost + // of this and decide if we should do the work to fill it + + mBufferList->LinkBuffer(mStart.mBuffer, new_buffer, mStart.mBuffer->mNext); } void diff --git a/parser/htmlparser/src/nsScanner.h b/parser/htmlparser/src/nsScanner.h index e904af37b25..28078699072 100644 --- a/parser/htmlparser/src/nsScanner.h +++ b/parser/htmlparser/src/nsScanner.h @@ -48,9 +48,8 @@ class nsScannerString : public nsSlidingString { nsScannerString(PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd); - virtual void InsertBuffer(PRUnichar* aStorageStart, - PRUnichar* aDataEnd, - PRUnichar* aStorageEnd); + virtual void InsertData(const PRUnichar* aDataStart, + const PRUnichar* aDataEnd); virtual void ReplaceCharacter(nsReadingIterator& aPosition, PRUnichar aChar); }; diff --git a/string/public/nsSharedBufferList.h b/string/public/nsSharedBufferList.h index 729278bed79..71c97bf5f21 100755 --- a/string/public/nsSharedBufferList.h +++ b/string/public/nsSharedBufferList.h @@ -54,7 +54,7 @@ * If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize * or else duplicate this class. */ -class nsSharedBufferList +class NS_COM nsSharedBufferList { public: @@ -165,7 +165,15 @@ class nsSharedBufferList public: void LinkBuffer( Buffer*, Buffer*, Buffer* ); Buffer* UnlinkBuffer( Buffer* ); - void SplitBuffer( const Position& ); + + enum SplitDisposition // when splitting a buffer in two... + { + kSplitCopyRightData, // copy the data right of the split point to a new buffer + kSplitCopyLeastData, // copy the smaller amount of data to the new buffer + kSplitCopyLeftData // copy the data left of the split point to a new buffer + }; + + void SplitBuffer( const Position&, SplitDisposition = kSplitCopyLeastData ); static Buffer* diff --git a/string/src/nsSharedBufferList.cpp b/string/src/nsSharedBufferList.cpp index 584890a75ec..4364201ffba 100755 --- a/string/src/nsSharedBufferList.cpp +++ b/string/src/nsSharedBufferList.cpp @@ -92,7 +92,7 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* } void -nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) +nsSharedBufferList::SplitBuffer( const Position& aSplitPosition, SplitDisposition aSplitDirection ) { Buffer* bufferToSplit = aSplitPosition.mBuffer; @@ -102,18 +102,23 @@ nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer"); - if ( (bufferToSplit->DataLength() >> 1) > splitOffset ) - { - Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); - LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); - bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); - } - else + // if the caller specifically asked to split off the right side of the buffer-to-be-split + // or else if they asked for the minimum amount of work, and that turned out to be the right side... + if ( aSplitDirection==kSplitCopyRightData || + ( aSplitDirection==kSplitCopyLeastData && ((bufferToSplit->DataLength() >> 1) <= splitOffset) ) ) { + // ...then allocate a new buffer initializing it by copying all the data _after_ the split in the source buffer (i.e., `split right') Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset)); LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext); bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer); } + else + { + // ...else move the data _before_ the split point (i.e., `split left') + Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); + LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); + bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); + } } diff --git a/xpcom/ds/nsSharedBufferList.cpp b/xpcom/ds/nsSharedBufferList.cpp index 584890a75ec..4364201ffba 100755 --- a/xpcom/ds/nsSharedBufferList.cpp +++ b/xpcom/ds/nsSharedBufferList.cpp @@ -92,7 +92,7 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* } void -nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) +nsSharedBufferList::SplitBuffer( const Position& aSplitPosition, SplitDisposition aSplitDirection ) { Buffer* bufferToSplit = aSplitPosition.mBuffer; @@ -102,18 +102,23 @@ nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer"); - if ( (bufferToSplit->DataLength() >> 1) > splitOffset ) - { - Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); - LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); - bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); - } - else + // if the caller specifically asked to split off the right side of the buffer-to-be-split + // or else if they asked for the minimum amount of work, and that turned out to be the right side... + if ( aSplitDirection==kSplitCopyRightData || + ( aSplitDirection==kSplitCopyLeastData && ((bufferToSplit->DataLength() >> 1) <= splitOffset) ) ) { + // ...then allocate a new buffer initializing it by copying all the data _after_ the split in the source buffer (i.e., `split right') Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset)); LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext); bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer); } + else + { + // ...else move the data _before_ the split point (i.e., `split left') + Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); + LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); + bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); + } } diff --git a/xpcom/ds/nsSharedBufferList.h b/xpcom/ds/nsSharedBufferList.h index 729278bed79..71c97bf5f21 100755 --- a/xpcom/ds/nsSharedBufferList.h +++ b/xpcom/ds/nsSharedBufferList.h @@ -54,7 +54,7 @@ * If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize * or else duplicate this class. */ -class nsSharedBufferList +class NS_COM nsSharedBufferList { public: @@ -165,7 +165,15 @@ class nsSharedBufferList public: void LinkBuffer( Buffer*, Buffer*, Buffer* ); Buffer* UnlinkBuffer( Buffer* ); - void SplitBuffer( const Position& ); + + enum SplitDisposition // when splitting a buffer in two... + { + kSplitCopyRightData, // copy the data right of the split point to a new buffer + kSplitCopyLeastData, // copy the smaller amount of data to the new buffer + kSplitCopyLeftData // copy the data left of the split point to a new buffer + }; + + void SplitBuffer( const Position&, SplitDisposition = kSplitCopyLeastData ); static Buffer* diff --git a/xpcom/string/public/nsSharedBufferList.h b/xpcom/string/public/nsSharedBufferList.h index 729278bed79..71c97bf5f21 100755 --- a/xpcom/string/public/nsSharedBufferList.h +++ b/xpcom/string/public/nsSharedBufferList.h @@ -54,7 +54,7 @@ * If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize * or else duplicate this class. */ -class nsSharedBufferList +class NS_COM nsSharedBufferList { public: @@ -165,7 +165,15 @@ class nsSharedBufferList public: void LinkBuffer( Buffer*, Buffer*, Buffer* ); Buffer* UnlinkBuffer( Buffer* ); - void SplitBuffer( const Position& ); + + enum SplitDisposition // when splitting a buffer in two... + { + kSplitCopyRightData, // copy the data right of the split point to a new buffer + kSplitCopyLeastData, // copy the smaller amount of data to the new buffer + kSplitCopyLeftData // copy the data left of the split point to a new buffer + }; + + void SplitBuffer( const Position&, SplitDisposition = kSplitCopyLeastData ); static Buffer* diff --git a/xpcom/string/src/nsSharedBufferList.cpp b/xpcom/string/src/nsSharedBufferList.cpp index 584890a75ec..4364201ffba 100755 --- a/xpcom/string/src/nsSharedBufferList.cpp +++ b/xpcom/string/src/nsSharedBufferList.cpp @@ -92,7 +92,7 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* } void -nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) +nsSharedBufferList::SplitBuffer( const Position& aSplitPosition, SplitDisposition aSplitDirection ) { Buffer* bufferToSplit = aSplitPosition.mBuffer; @@ -102,18 +102,23 @@ nsSharedBufferList::SplitBuffer( const Position& aSplitPosition ) NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer"); - if ( (bufferToSplit->DataLength() >> 1) > splitOffset ) - { - Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); - LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); - bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); - } - else + // if the caller specifically asked to split off the right side of the buffer-to-be-split + // or else if they asked for the minimum amount of work, and that turned out to be the right side... + if ( aSplitDirection==kSplitCopyRightData || + ( aSplitDirection==kSplitCopyLeastData && ((bufferToSplit->DataLength() >> 1) <= splitOffset) ) ) { + // ...then allocate a new buffer initializing it by copying all the data _after_ the split in the source buffer (i.e., `split right') Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset)); LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext); bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer); } + else + { + // ...else move the data _before_ the split point (i.e., `split left') + Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset)); + LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit); + bufferToSplit->DataStart(aSplitPosition.mPosInBuffer); + } }