From 7a461c49a4441ce8a884cdfedabf218d68134eaa Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Thu, 25 Nov 2004 07:03:20 +0000 Subject: [PATCH] Reduce string copying and allocation in the parser by only copying the scanner buffer when we need to mutate the string. Allow a nsDependentString / nsDependentSubstring to be created without being bound to anything. Move StripChar() onto nsSubstring from nsString. Bug 269853, r=jst, sr=darin. git-svn-id: svn://10.0.0.236/trunk@165773 18797224-902f-48f8-a5cc-f745e15eee43 --- .../parser/htmlparser/public/nsHTMLTokens.h | 6 +- .../htmlparser/public/nsScannerString.h | 56 ++++++++- .../parser/htmlparser/src/nsHTMLTokens.cpp | 108 +++++++++++------- mozilla/parser/htmlparser/src/nsScanner.cpp | 102 +++++++++++++---- mozilla/parser/htmlparser/src/nsScanner.h | 11 +- .../parser/htmlparser/src/nsScannerString.cpp | 86 ++++++++++++-- mozilla/xpcom/build/dlldeps.cpp | 4 + .../xpcom/string/public/nsTDependentString.h | 17 +-- .../string/public/nsTDependentSubstring.h | 16 ++- mozilla/xpcom/string/public/nsTString.h | 11 -- mozilla/xpcom/string/public/nsTSubstring.h | 10 ++ mozilla/xpcom/string/src/Makefile.in | 1 + .../xpcom/string/src/nsDependentString.cpp | 51 +++++++++ .../xpcom/string/src/nsTDependentString.cpp | 50 ++++++++ .../string/src/nsTDependentSubstring.cpp | 19 +++ .../xpcom/string/src/nsTStringObsolete.cpp | 24 ---- mozilla/xpcom/string/src/nsTSubstring.cpp | 24 ++++ 17 files changed, 458 insertions(+), 138 deletions(-) create mode 100644 mozilla/xpcom/string/src/nsDependentString.cpp create mode 100755 mozilla/xpcom/string/src/nsTDependentString.cpp diff --git a/mozilla/parser/htmlparser/public/nsHTMLTokens.h b/mozilla/parser/htmlparser/public/nsHTMLTokens.h index e70e450ad04..29b4cde26c6 100644 --- a/mozilla/parser/htmlparser/public/nsHTMLTokens.h +++ b/mozilla/parser/htmlparser/public/nsHTMLTokens.h @@ -265,7 +265,7 @@ public: virtual const nsSubstring& GetStringValue(void); protected: - nsString mTextValue; + nsScannerSharedSubstring mTextValue; }; /** @@ -363,7 +363,7 @@ public: virtual void SetKey(const nsAString& aKey); virtual void BindKey(nsScanner* aScanner, nsScannerIterator& aStart, nsScannerIterator& aEnd); - const nsString& GetValue(void) {return mTextValue;} + const nsSubstring& GetValue(void) {return mTextValue.str();} virtual void SanitizeKey(); virtual const nsSubstring& GetStringValue(void); virtual void GetSource(nsString& anOutputString); @@ -374,7 +374,7 @@ protected: #ifdef DEBUG PRPackedBool mLastAttribute; #endif - nsAutoString mTextValue; + nsScannerSharedSubstring mTextValue; nsScannerSubstring mTextKey; }; diff --git a/mozilla/parser/htmlparser/public/nsScannerString.h b/mozilla/parser/htmlparser/public/nsScannerString.h index dcdd5ecdd0a..1d50e963d87 100644 --- a/mozilla/parser/htmlparser/public/nsScannerString.h +++ b/mozilla/parser/htmlparser/public/nsScannerString.h @@ -273,8 +273,10 @@ class nsScannerSubstring size_type mLength; // these fields are used to implement AsString - nsString mFlattenedRep; + nsDependentSubstring mFlattenedRep; PRBool mIsDirty; + + friend class nsScannerSharedSubstring; }; @@ -301,6 +303,52 @@ class nsScannerString : public nsScannerSubstring }; + /** + * nsScannerSharedSubstring implements copy-on-write semantics for + * nsScannerSubstring. When you call .writable(), it will copy the data + * and return a mutable string object. This class also manages releasing + * the reference to the scanner buffer when it is no longer needed. + */ + +class nsScannerSharedSubstring + { + public: + nsScannerSharedSubstring() + : mBuffer(nsnull), mBufferList(nsnull) { } + + ~nsScannerSharedSubstring() + { + if (mBufferList) + ReleaseBuffer(); + } + + // Acquire a copy-on-write reference to the given substring. + NS_HIDDEN_(void) Rebind(const nsScannerIterator& aStart, + const nsScannerIterator& aEnd); + + // Get a mutable reference to this string + nsSubstring& writable() + { + if (mBufferList) + MakeMutable(); + + return mString; + } + + // Get a const reference to this string + const nsSubstring& str() const { return mString; } + + private: + typedef nsScannerBufferList::Buffer Buffer; + + NS_HIDDEN_(void) ReleaseBuffer(); + NS_HIDDEN_(void) MakeMutable(); + + nsDependentSubstring mString; + Buffer *mBuffer; + nsScannerBufferList *mBufferList; + }; + /** * nsScannerIterator works just like nsReadingIterator except that * it knows how to iterate over a list of scanner buffers. @@ -322,6 +370,7 @@ class nsScannerIterator const nsScannerSubstring* mOwner; friend class nsScannerSubstring; + friend class nsScannerSharedSubstring; public: nsScannerIterator() {} @@ -553,6 +602,11 @@ AppendUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest ) AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest); } +void +AppendUnicodeTo( const nsScannerIterator& aSrcStart, + const nsScannerIterator& aSrcEnd, + nsScannerSharedSubstring& aDest ); + PRBool FindCharInReadable( PRUnichar aChar, nsScannerIterator& aStart, diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp b/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp index b46a6315d1e..d8bb3046037 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp @@ -180,18 +180,20 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag //NOTE: We don't Consume the tag attributes here, nor do we eat the ">" nsresult result=NS_OK; + nsScannerSharedSubstring tagIdent; + if (aFlag & NS_IPARSER_FLAG_HTML) { - nsAutoString theSubstr; - result=aScanner.ReadTagIdentifier(theSubstr); - mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr); + result = aScanner.ReadTagIdentifier(tagIdent); + mTypeID = (PRInt32)nsHTMLTags::LookupTag(tagIdent.str()); // Save the original tag string if this is user-defined or if we // are viewing source if(eHTMLTag_userdefined==mTypeID || (aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) { - mTextValue=theSubstr; + mTextValue = tagIdent.str(); } } else { - result=aScanner.ReadTagIdentifier(mTextValue); + result = aScanner.ReadTagIdentifier(tagIdent); + mTextValue = tagIdent.str(); mTypeID = nsHTMLTags::LookupTag(mTextValue); } @@ -283,21 +285,22 @@ CEndToken::CEndToken(const nsAString& aName,eHTMLTags aTag) : CHTMLToken(aTag) { nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag) { nsresult result = NS_OK; + nsScannerSharedSubstring tagIdent; + if (aFlag & NS_IPARSER_FLAG_HTML) { - nsAutoString theSubstr; - result=aScanner.ReadTagIdentifier(theSubstr); + result = aScanner.ReadTagIdentifier(tagIdent); - mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr); + mTypeID = (PRInt32)nsHTMLTags::LookupTag(tagIdent.str()); // Save the original tag string if this is user-defined or if we // are viewing source if(eHTMLTag_userdefined==mTypeID || (aFlag & (NS_IPARSER_FLAG_VIEW_SOURCE | NS_IPARSER_FLAG_PRESERVE_CONTENT))) { - mTextValue=theSubstr; + mTextValue = tagIdent.str(); } } else { - result = aScanner.ReadTagIdentifier(mTextValue); - + result = aScanner.ReadTagIdentifier(tagIdent); + mTextValue = tagIdent.str(); mTypeID = nsHTMLTags::LookupTag(mTextValue); } @@ -1330,7 +1333,7 @@ CAttributeToken::CAttributeToken() : CHTMLToken(eHTMLTag_unknown) { * @return */ CAttributeToken::CAttributeToken(const nsAString& aName) : CHTMLToken(eHTMLTag_unknown) { - mTextValue.Assign(aName); + mTextValue.writable().Assign(aName); mHasEqualWithoutValue=PR_FALSE; #ifdef DEBUG mLastAttribute = PR_FALSE; @@ -1346,7 +1349,7 @@ CAttributeToken::CAttributeToken(const nsAString& aName) : CHTMLToken(eHTMLTag_u * @return */ CAttributeToken::CAttributeToken(const nsAString& aKey, const nsAString& aName) : CHTMLToken(eHTMLTag_unknown) { - mTextValue.Assign(aName); + mTextValue.writable().Assign(aName); mTextKey.Rebind(aKey); mHasEqualWithoutValue=PR_FALSE; #ifdef DEBUG @@ -1402,7 +1405,7 @@ void CAttributeToken::SanitizeKey() { const nsSubstring& CAttributeToken::GetStringValue(void) { - return mTextValue; + return mTextValue.str(); } /* @@ -1426,13 +1429,13 @@ void CAttributeToken::GetSource(nsString& anOutputString){ */ void CAttributeToken::AppendSourceTo(nsAString& anOutputString){ AppendUnicodeTo(mTextKey, anOutputString); - if(mTextValue.Length() || mHasEqualWithoutValue) + if(mTextValue.str().Length() || mHasEqualWithoutValue) anOutputString.AppendLiteral("="); - anOutputString.Append(mTextValue); + anOutputString.Append(mTextValue.str()); // anOutputString.AppendLiteral(";"); } -static void AppendNCR(nsString& aString, PRInt32 aNCRValue); +static void AppendNCR(nsSubstring& aString, PRInt32 aNCRValue); /* * @param aScanner -- controller of underlying input source * @param aFlag -- If NS_IPARSER_FLAG_VIEW_SOURCE do not reduce entities... @@ -1440,7 +1443,7 @@ static void AppendNCR(nsString& aString, PRInt32 aNCRValue); * */ static -nsresult ConsumeAttributeEntity(nsString& aString, +nsresult ConsumeAttributeEntity(nsScannerSharedSubstring& aString, nsScanner& aScanner, PRInt32 aFlag) { @@ -1464,37 +1467,40 @@ nsresult ConsumeAttributeEntity(nsString& aString, // Nav 4.x does not treat it as an entity, // IE treats it as an entity if terminated with a semicolon. // Resembling IE!! + + nsSubstring &writable = aString.writable(); if(theNCRValue < 0 || (theNCRValue > 255 && theTermChar != ';')) { // Looks like we're not dealing with an entity - aString.Append(kAmpersand); - aString.Append(entity); + writable.Append(kAmpersand); + writable.Append(entity); } else { // A valid entity so reduce it. - aString.Append(PRUnichar(theNCRValue)); + writable.Append(PRUnichar(theNCRValue)); } } } else if (ch==kHashsign && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) { result=CEntityToken::ConsumeEntity(ch,entity,aScanner); if (NS_SUCCEEDED(result)) { + nsSubstring &writable = aString.writable(); if (result == NS_HTMLTOKENS_NOT_AN_ENTITY) { // Looked like an entity but it's not aScanner.GetChar(amp); - aString.Append(amp); + writable.Append(amp); result = NS_OK; // just being safe.. } else { PRInt32 err; theNCRValue=entity.ToInteger(&err,kAutoDetect); - AppendNCR(aString, theNCRValue); + AppendNCR(writable, theNCRValue); } } } else { // What we thought as entity is not really an entity... aScanner.GetChar(amp); - aString.Append(amp); + aString.writable().Append(amp); }//if } @@ -1516,7 +1522,7 @@ nsresult ConsumeAttributeEntity(nsString& aString, * @return error result */ static -nsresult ConsumeAttributeValueText(nsString& aString, +nsresult ConsumeAttributeValueText(nsScannerSharedSubstring& aString, PRInt32& aNewlineCount, nsScanner& aScanner, const nsReadEndCondition& aEndCondition, @@ -1538,19 +1544,20 @@ nsresult ConsumeAttributeValueText(nsString& aString, aScanner.GetChar(ch); result = aScanner.Peek(ch); if (NS_SUCCEEDED(result)) { + nsSubstring &writable = aString.writable(); if(ch == kNewLine) { - aString.AppendLiteral("\r\n"); + writable.AppendLiteral("\r\n"); aScanner.GetChar(ch); } else { - aString.Append(PRUnichar('\r')); + writable.Append(PRUnichar('\r')); } ++aNewlineCount; } } else if(ch == kNewLine && aAllowNewlines) { aScanner.GetChar(ch); - aString.Append(PRUnichar('\n')); + aString.writable().Append(PRUnichar('\n')); ++aNewlineCount; } else { @@ -1573,14 +1580,14 @@ nsresult ConsumeAttributeValueText(nsString& aString, */ static nsresult ConsumeQuotedString(PRUnichar aChar, - nsString& aString, + nsScannerSharedSubstring& aString, PRInt32& aNewlineCount, nsScanner& aScanner, PRInt32 aFlag) { NS_ASSERTION(aChar==kQuote || aChar==kApostrophe,"char is neither quote nor apostrophe"); // hold onto this in case this is an unterminated string literal - PRUint32 origLen = aString.Length(); + PRUint32 origLen = aString.str().Length(); static const PRUnichar theTerminalCharsQuote[] = { PRUnichar(kQuote), PRUnichar('&'), PRUnichar(kCR), @@ -1612,11 +1619,11 @@ nsresult ConsumeQuotedString(PRUnichar aChar, // Ref: Bug 35806 // A back up measure when disaster strikes... // Ex DecrementUsageCount(); + mBufferList->DiscardUnreferencedPrefix(mBuffer); + mBufferList->Release(); +} + +void +nsScannerSharedSubstring::MakeMutable() +{ + nsString temp(mString); // this will force a copy of the data + mString.Assign(temp); // mString will now share the just-allocated buffer + + ReleaseBuffer(); + + mBuffer = nsnull; + mBufferList = nsnull; +} + /** * utils -- based on code from nsReadableUtils.cpp */ @@ -446,6 +496,22 @@ CopyUnicodeTo( const nsScannerIterator& aSrcStart, copy_string(fromBegin, aSrcEnd, writer); } +void +AppendUnicodeTo( const nsScannerIterator& aSrcStart, + const nsScannerIterator& aSrcEnd, + nsScannerSharedSubstring& aDest ) + { + // Check whether we can just create a dependent string. + if (aDest.str().IsEmpty()) { + // We can just make |aDest| point to the buffer. + // This will take care of copying if the buffer spans fragments. + aDest.Rebind(aSrcStart, aSrcEnd); + } else { + // The dest string is not empty, so it can't be a dependent substring. + AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable()); + } + } + void AppendUnicodeTo( const nsScannerIterator& aSrcStart, const nsScannerIterator& aSrcEnd, diff --git a/mozilla/xpcom/build/dlldeps.cpp b/mozilla/xpcom/build/dlldeps.cpp index f54c6faaefc..5753ece06d5 100644 --- a/mozilla/xpcom/build/dlldeps.cpp +++ b/mozilla/xpcom/build/dlldeps.cpp @@ -197,4 +197,8 @@ void XXXNeverCalled() } NS_NewInterfaceRequestorAggregation(nsnull, nsnull, nsnull); NS_NewHashPropertyBag(nsnull); + nsDependentString depstring; + depstring.Rebind(nsnull, PRUint32(0)); + nsDependentCString depcstring; + depcstring.Rebind(nsnull, PRUint32(0)); } diff --git a/mozilla/xpcom/string/public/nsTDependentString.h b/mozilla/xpcom/string/public/nsTDependentString.h index 91a2b53ee92..7975153714f 100644 --- a/mozilla/xpcom/string/public/nsTDependentString.h +++ b/mozilla/xpcom/string/public/nsTDependentString.h @@ -98,6 +98,10 @@ class nsTDependentString_CharT : public nsTString_CharT AssertValid(); } + // Create a nsTDependentSubstring to be bound later + nsTDependentString_CharT() + : string_type() {} + // XXX are you sure?? // auto-generated copy-constructor OK // auto-generated copy-assignment operator OK @@ -110,19 +114,10 @@ class nsTDependentString_CharT : public nsTString_CharT void Rebind( const char_type* data ) { - mData = NS_CONST_CAST(char_type*, data); - mLength = char_traits::length(data); - SetDataFlags(F_TERMINATED); - AssertValid(); + Rebind(data, char_traits::length(data)); } - void Rebind( const char_type* data, size_type length ) - { - mData = NS_CONST_CAST(char_type*, data); - mLength = length; - SetDataFlags(F_TERMINATED); - AssertValid(); - } + NS_COM void Rebind( const char_type* data, size_type length ); void Rebind( const char_type* start, const char_type* end ) { diff --git a/mozilla/xpcom/string/public/nsTDependentSubstring.h b/mozilla/xpcom/string/public/nsTDependentSubstring.h index 89d96e13de4..f57605a7325 100644 --- a/mozilla/xpcom/string/public/nsTDependentSubstring.h +++ b/mozilla/xpcom/string/public/nsTDependentSubstring.h @@ -52,22 +52,16 @@ class nsTDependentSubstring_CharT : public nsTSubstring_CharT NS_COM void Rebind( const abstract_string_type&, PRUint32 startPos, PRUint32 length = size_type(-1) ); NS_COM void Rebind( const substring_type&, PRUint32 startPos, PRUint32 length = size_type(-1) ); - void Rebind( const char_type* start, const char_type* end ) - { - NS_ASSERTION(start && end, "nsTDependentSubstring must wrap a non-NULL buffer"); - mData = NS_CONST_CAST(char_type*, start); - mLength = end - start; - SetDataFlags(F_NONE); - } + NS_COM void Rebind( const char_type* start, const char_type* end ); nsTDependentSubstring_CharT( const abstract_string_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) ) - : substring_type(F_NONE) + : substring_type() { Rebind(str, startPos, length); } nsTDependentSubstring_CharT( const substring_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) ) - : substring_type(F_NONE) + : substring_type() { Rebind(str, startPos, length); } @@ -78,6 +72,10 @@ class nsTDependentSubstring_CharT : public nsTSubstring_CharT nsTDependentSubstring_CharT( const const_iterator& start, const const_iterator& end ) : substring_type(NS_CONST_CAST(char_type*, start.get()), end.get() - start.get(), F_NONE) {} + // Create a nsTDependentSubstring to be bound later + nsTDependentSubstring_CharT() + : substring_type() {} + // auto-generated copy-constructor OK (XXX really?? what about base class copy-ctor?) private: diff --git a/mozilla/xpcom/string/public/nsTString.h b/mozilla/xpcom/string/public/nsTString.h index 0767e256f6f..d8ca1a2c58c 100644 --- a/mozilla/xpcom/string/public/nsTString.h +++ b/mozilla/xpcom/string/public/nsTString.h @@ -343,17 +343,6 @@ class nsTString_CharT : public nsTSubstring_CharT NS_COM void StripChars( const char* aSet ); - /** - * This method is used to remove all occurances of aChar from this - * string. - * - * @param aChar -- char to be stripped - * @param aOffset -- where in this string to start stripping chars - */ - - NS_COM void StripChar( char_type aChar, PRInt32 aOffset=0 ); - - /** * This method strips whitespace throughout the string. */ diff --git a/mozilla/xpcom/string/public/nsTSubstring.h b/mozilla/xpcom/string/public/nsTSubstring.h index b85951a5b6e..b30ddc8ce19 100644 --- a/mozilla/xpcom/string/public/nsTSubstring.h +++ b/mozilla/xpcom/string/public/nsTSubstring.h @@ -392,6 +392,16 @@ class nsTSubstring_CharT : public nsTAString_CharT NS_COM void NS_FASTCALL SetIsVoid( PRBool ); + /** + * This method is used to remove all occurances of aChar from this + * string. + * + * @param aChar -- char to be stripped + * @param aOffset -- where in this string to start stripping chars + */ + + NS_COM void StripChar( char_type aChar, PRInt32 aOffset=0 ); + public: diff --git a/mozilla/xpcom/string/src/Makefile.in b/mozilla/xpcom/string/src/Makefile.in index 81033c6c953..202485e39e2 100644 --- a/mozilla/xpcom/string/src/Makefile.in +++ b/mozilla/xpcom/string/src/Makefile.in @@ -53,6 +53,7 @@ REQUIRES = xpcom \ CPPSRCS = \ nsAString.cpp \ + nsDependentString.cpp \ nsDependentSubstring.cpp \ nsObsoleteAStringThunk.cpp \ nsPrintfCString.cpp \ diff --git a/mozilla/xpcom/string/src/nsDependentString.cpp b/mozilla/xpcom/string/src/nsDependentString.cpp new file mode 100644 index 00000000000..0f4464dd930 --- /dev/null +++ b/mozilla/xpcom/string/src/nsDependentString.cpp @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by IBM Corporation are Copyright (C) 2004 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * Brian Ryner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsDependentString.h" +#include "nsAlgorithm.h" + + // define nsDependentString +#include "string-template-def-unichar.h" +#include "nsTDependentString.cpp" +#include "string-template-undef.h" + + // define nsDependentCString +#include "string-template-def-char.h" +#include "nsTDependentString.cpp" +#include "string-template-undef.h" diff --git a/mozilla/xpcom/string/src/nsTDependentString.cpp b/mozilla/xpcom/string/src/nsTDependentString.cpp new file mode 100755 index 00000000000..ac5b83a4236 --- /dev/null +++ b/mozilla/xpcom/string/src/nsTDependentString.cpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by IBM Corporation are Copyright (C) 2004 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher + * Brian Ryner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +void +nsTDependentString_CharT::Rebind( const char_type* data, size_type length ) + { + // If we currently own a buffer, release it. + Finalize(); + + mData = NS_CONST_CAST(char_type*, data); + mLength = length; + SetDataFlags(F_TERMINATED); + AssertValid(); + } diff --git a/mozilla/xpcom/string/src/nsTDependentSubstring.cpp b/mozilla/xpcom/string/src/nsTDependentSubstring.cpp index 8421ecc0d29..8eeb904bad8 100644 --- a/mozilla/xpcom/string/src/nsTDependentSubstring.cpp +++ b/mozilla/xpcom/string/src/nsTDependentSubstring.cpp @@ -39,6 +39,9 @@ void nsTDependentSubstring_CharT::Rebind( const abstract_string_type& readable, PRUint32 startPos, PRUint32 length ) { + // If we currently own a buffer, release it. + Finalize(); + size_type strLength = readable.GetReadableBuffer((const char_type**) &mData); if (startPos > strLength) @@ -53,6 +56,9 @@ nsTDependentSubstring_CharT::Rebind( const abstract_string_type& readable, PRUin void nsTDependentSubstring_CharT::Rebind( const substring_type& str, PRUint32 startPos, PRUint32 length ) { + // If we currently own a buffer, release it. + Finalize(); + size_type strLength = str.Length(); if (startPos > strLength) @@ -63,3 +69,16 @@ nsTDependentSubstring_CharT::Rebind( const substring_type& str, PRUint32 startPo SetDataFlags(F_NONE); } + +void +nsTDependentSubstring_CharT::Rebind( const char_type* start, const char_type* end ) + { + NS_ASSERTION(start && end, "nsTDependentSubstring must wrap a non-NULL buffer"); + + // If we currently own a buffer, release it. + Finalize(); + + mData = NS_CONST_CAST(char_type*, start); + mLength = end - start; + SetDataFlags(F_NONE); + } diff --git a/mozilla/xpcom/string/src/nsTStringObsolete.cpp b/mozilla/xpcom/string/src/nsTStringObsolete.cpp index 5ed065ad2e8..c1425a6ba07 100644 --- a/mozilla/xpcom/string/src/nsTStringObsolete.cpp +++ b/mozilla/xpcom/string/src/nsTStringObsolete.cpp @@ -299,30 +299,6 @@ nsTString_CharT::StripChars( const char* aSet ) mLength = nsBufferRoutines::strip_chars(mData, mLength, aSet); } -void -nsTString_CharT::StripChar( char_type aChar, PRInt32 aOffset ) - { - if (mLength == 0 || aOffset >= PRInt32(mLength)) - return; - - EnsureMutable(); // XXX do this lazily? - - // XXXdarin this code should defer writing until necessary. - - char_type* to = mData + aOffset; - char_type* from = mData + aOffset; - char_type* end = mData + mLength; - - while (from < end) - { - char_type theChar = *from++; - if (aChar != theChar) - *to++ = theChar; - } - *to = char_type(0); // add the null - mLength = to - mData; - } - void nsTString_CharT::StripWhitespace() { diff --git a/mozilla/xpcom/string/src/nsTSubstring.cpp b/mozilla/xpcom/string/src/nsTSubstring.cpp index b874b90a36a..cbe47fa9b15 100644 --- a/mozilla/xpcom/string/src/nsTSubstring.cpp +++ b/mozilla/xpcom/string/src/nsTSubstring.cpp @@ -664,3 +664,27 @@ nsTSubstring_CharT::FindChar( char_type c, index_type offset ) const } return -1; } + +void +nsTSubstring_CharT::StripChar( char_type aChar, PRInt32 aOffset ) + { + if (mLength == 0 || aOffset >= PRInt32(mLength)) + return; + + EnsureMutable(); // XXX do this lazily? + + // XXXdarin this code should defer writing until necessary. + + char_type* to = mData + aOffset; + char_type* from = mData + aOffset; + char_type* end = mData + mLength; + + while (from < end) + { + char_type theChar = *from++; + if (aChar != theChar) + *to++ = theChar; + } + *to = char_type(0); // add the null + mLength = to - mData; + }