From 7791c7b9e8e88ea46cdcb741e80b428233834e2a Mon Sep 17 00:00:00 2001 From: "scc%mozilla.org" Date: Fri, 30 Mar 2001 13:15:41 +0000 Subject: [PATCH] untemplatize |nsPromiseFlat[C]String| so windows and linux can build git-svn-id: svn://10.0.0.236/branches/STRING_081_BRANCH@90887 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/string/macbuild/string.mcp | Bin 73563 -> 75711 bytes mozilla/string/obsolete/nsString.cpp | 5 + mozilla/string/obsolete/nsString.h | 1 + mozilla/string/obsolete/nsString2.cpp | 7 + mozilla/string/obsolete/nsString2.h | 1 + mozilla/string/public/nsAPromiseString.h | 6 +- mozilla/string/public/nsBufferHandle.h | 8 + mozilla/string/public/nsBufferHandleUtils.h | 65 ++++++ mozilla/string/public/nsCommonString.h | 60 +++++- mozilla/string/public/nsDependentString.h | 6 +- mozilla/string/public/nsDependentSubstring.h | 4 - mozilla/string/public/nsLocalString.h | 6 +- .../string/public/nsPrivateSharableString.h | 8 + mozilla/string/public/nsPromiseFlatString.h | 199 +++++++++--------- mozilla/string/public/nsPromiseSubstring.h | 4 - mozilla/string/public/nsSharableString.h | 60 +++++- mozilla/string/public/nsStringTraits.h | 4 + mozilla/string/src/nsCommonString.cpp | 31 +++ mozilla/string/src/nsSharableString.cpp | 31 +++ mozilla/xpcom/string/macbuild/string.mcp | Bin 73563 -> 75711 bytes mozilla/xpcom/string/obsolete/nsString.cpp | 5 + mozilla/xpcom/string/obsolete/nsString.h | 1 + mozilla/xpcom/string/obsolete/nsString2.cpp | 7 + mozilla/xpcom/string/obsolete/nsString2.h | 1 + .../xpcom/string/public/nsAPromiseString.h | 6 +- mozilla/xpcom/string/public/nsBufferHandle.h | 8 + .../xpcom/string/public/nsBufferHandleUtils.h | 65 ++++++ mozilla/xpcom/string/public/nsCommonString.h | 60 +++++- .../xpcom/string/public/nsDependentString.h | 6 +- .../string/public/nsDependentSubstring.h | 4 - mozilla/xpcom/string/public/nsLocalString.h | 6 +- .../string/public/nsPrivateSharableString.h | 8 + .../xpcom/string/public/nsPromiseFlatString.h | 199 +++++++++--------- .../xpcom/string/public/nsPromiseSubstring.h | 4 - .../xpcom/string/public/nsSharableString.h | 60 +++++- mozilla/xpcom/string/public/nsStringTraits.h | 4 + mozilla/xpcom/string/src/nsCommonString.cpp | 31 +++ mozilla/xpcom/string/src/nsSharableString.cpp | 31 +++ 38 files changed, 760 insertions(+), 252 deletions(-) diff --git a/mozilla/string/macbuild/string.mcp b/mozilla/string/macbuild/string.mcp index 43f759e387bcd71b3c9a11a7add300bf893bba37..8f2584ee852e8597665aec89e9ca9bb3ab23be68 100644 GIT binary patch delta 1591 zcmZ9MYiJx*6oBuYoqbI<*=+V{)=i>G+qJRTCe8*$?87{o;%X+@rhq>EBJX;)}zg@P2Z*5V&QeEf_4^M?kZ!g}uHOj5jX=9_cx zIrpA(=FI)+rg-a~7%Hl2g%IK(geD1%uM(Q@e-Vm$bwy-vWN$ck!s4*L_u0}2yzHUy z07(P#AWMWee<8#Jub{6K)y2x|FR9vWsjgOzmc|Pj%v*i}ynt}O6v!Spjvu+9i=cy~ z*-0s$<_a0$kKOz+$sbc7!ytA9vaRFJGW$)+PUK)V4>5g>G3AIhsf& z%DfgVm%VM5X%~wGPWzkP$qhN;W?!c0hDW5-uKP-B_bnW=YIJdmIalGgV=%Ki=?Vsmrf!dEt@+lyk? z!y)tXk-Qm*pPLOFQThwAqRrM)o4NAR|b5oxLQD6Hg(d$e2a; z{d>!?&GL$(R;u&gknm8Zgw)DrVdeo% z?1nAi1RSFEK6cGAp}Q;-Hup+|`?OjY53l=7!T$gE*}v|yWfn~Sp=M)k$?f6MVdQ;W z*$n<_gL>Rn<8Q3pI={hj0@aUdfK=b zrV(MS(OeDF4+Np*H`Ex7ba!@gA8@XNF{ES5*zMV@Cq{+at@br5nv)95xYxexo-5C%+0AZk!BNv4^x|OvAeCK-_XV JlAwRm{{RJQN4)?5 delta 1283 zcma)+OGs2v7{|}Kb9G+ojLztYGNU;@Mr)eUL7_$D;4>5(m60eg(S;59!m*+UIG`y6 zCAYH}BGlXkMwqv_i$Vw5MQRbW>4CHemu-?#&wQb=SzYLLBs7e%Sf!M>a}un)Ogtljd)=!bpOLe#OZ?LPUT zt&>up6b#B$`N}EgzUh!lhl2uZ=+4pq$h4~JUY6X^Z5O1Fp81TgrRE{_E!-xBs@Sjm zK^6|bW6$=B^xO0I3Au7dUg_(RuM zZkXkxNPFQl?5nu-Y-bBlhZK+*ND-+=W+IJ9Lt9Tc1ed~_kU4R6a3nGW!y^1#g)||L zBh8$A{ZbUNklDx_qy>2r=|cLDexwzdi}WCCkk!aMqzyRD51x-g8Pbb%Bg>H|GzZn` zqLciT=~LC=oJwRZvIJRyEIuw{2##U7F+Kn?g@Gn1dVQb z4|#e~jlQUYo={4TQIpU`w5D)l>9(|~G1chi^DrZAs?q10K!2fJcXLyd)-?G$O4%-J VO*Ojtvc^=SZ;dBScPi*l`VSih4%h$y diff --git a/mozilla/string/obsolete/nsString.cpp b/mozilla/string/obsolete/nsString.cpp index 2ec4f28fec5..2bad4c8dbb6 100644 --- a/mozilla/string/obsolete/nsString.cpp +++ b/mozilla/string/obsolete/nsString.cpp @@ -42,6 +42,11 @@ static const char* kPossibleNull = "Error: possible unintended null in string"; static const char* kNullPointerError = "Error: unexpected null ptr"; static const char* kWhitespace="\b\t\r\n "; +const nsBufferHandle* +nsCString::GetFlatBufferHandle() const + { + return NS_REINTERPRET_CAST(const nsBufferHandle*, 1); + } static void CSubsume(nsStr& aDest,nsStr& aSource){ if(aSource.mStr && aSource.mLength) { diff --git a/mozilla/string/obsolete/nsString.h b/mozilla/string/obsolete/nsString.h index 49f6c93a893..9bf13d1f692 100644 --- a/mozilla/string/obsolete/nsString.h +++ b/mozilla/string/obsolete/nsString.h @@ -70,6 +70,7 @@ class NS_COM nsCString : public nsStr { protected: + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const char* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual char* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ); diff --git a/mozilla/string/obsolete/nsString2.cpp b/mozilla/string/obsolete/nsString2.cpp index 50b06ab680a..78963ffea58 100644 --- a/mozilla/string/obsolete/nsString2.cpp +++ b/mozilla/string/obsolete/nsString2.cpp @@ -39,6 +39,13 @@ static const char* kPossibleNull = "Error: possible unintended null in string"; static const char* kNullPointerError = "Error: unexpected null ptr"; static const char* kWhitespace="\b\t\r\n "; +const nsBufferHandle* +nsString::GetFlatBufferHandle() const + { + return NS_REINTERPRET_CAST(const nsBufferHandle*, 1); + } + + static void Subsume(nsStr& aDest,nsStr& aSource){ if(aSource.mStr && aSource.mLength) { diff --git a/mozilla/string/obsolete/nsString2.h b/mozilla/string/obsolete/nsString2.h index a710d5ce255..d7698322cd2 100644 --- a/mozilla/string/obsolete/nsString2.h +++ b/mozilla/string/obsolete/nsString2.h @@ -73,6 +73,7 @@ class NS_COM nsString : public nsStr { protected: + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const PRUnichar* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual PRUnichar* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ); diff --git a/mozilla/string/public/nsAPromiseString.h b/mozilla/string/public/nsAPromiseString.h index 1c0885f9f27..70bb5187785 100644 --- a/mozilla/string/public/nsAPromiseString.h +++ b/mozilla/string/public/nsAPromiseString.h @@ -26,12 +26,10 @@ #ifndef nsAPromiseString_h___ #define nsAPromiseString_h___ -#ifndef nsAString_h___ -#include "nsAString.h" -#endif - /** + * Don't |#include| this file yourself. You will get it automatically if you need it. * + * Why is it a separate file? To make it easier to find the classes in your local tree. */ class NS_COM nsAPromiseString : public nsAString { }; diff --git a/mozilla/string/public/nsBufferHandle.h b/mozilla/string/public/nsBufferHandle.h index 89f284085fb..0cd7e1d547e 100755 --- a/mozilla/string/public/nsBufferHandle.h +++ b/mozilla/string/public/nsBufferHandle.h @@ -180,6 +180,14 @@ class nsSharedBufferHandle mFlags = kIsShared; } + nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT*, CharT*, PRBool isSingleAllocation ) + : nsBufferHandle(aDataStart, aDataEnd) + { + mFlags = kIsShared; + if ( isSingleAllocation ) + mFlags |= kIsSingleAllocationWithBuffer; + } + ~nsSharedBufferHandle(); void diff --git a/mozilla/string/public/nsBufferHandleUtils.h b/mozilla/string/public/nsBufferHandleUtils.h index ed09b164a39..565ac3b64f0 100644 --- a/mozilla/string/public/nsBufferHandleUtils.h +++ b/mozilla/string/public/nsBufferHandleUtils.h @@ -37,6 +37,71 @@ // for placement |new| +template +class nsAutoBufferHandle + { + public: + nsAutoBufferHandle() : mHandle(0) { } + + nsAutoBufferHandle( const nsAutoBufferHandle& aOther ) + : mHandle(aOther.get()) + { + if ( mHandle) + mHandle->AcquireReference(); + } + + explicit + nsAutoBufferHandle( const nsSharedBufferHandle* aHandle ) + : mHandle(aHandle) + { + if ( mHandle) + mHandle->AcquireReference(); + } + + ~nsAutoBufferHandle() + { + if ( mHandle ) + mHandle->ReleaseReference(); + } + + nsAutoBufferHandle& + operator=( const nsSharedBufferHandle* rhs ) + { + nsSharedBufferHandle* old_handle = mHandle; + if ( (mHandle = NS_CONST_CAST(nsSharedBufferHandle*, rhs)) ) + mHandle->AcquireReference(); + if ( old_handle ) + old_handle->ReleaseReference(); + return *this; + } + + nsAutoBufferHandle& + operator=( const nsAutoBufferHandle& rhs ) + { + return operator=(rhs.get()); + } + + nsSharedBufferHandle* + get() const + { + return mHandle; + } + + operator nsSharedBufferHandle*() const + { + return get(); + } + + nsSharedBufferHandle* + operator->() const + { + return get(); + } + + private: + nsSharedBufferHandle* mHandle; + }; + template inline diff --git a/mozilla/string/public/nsCommonString.h b/mozilla/string/public/nsCommonString.h index 3894c57b449..64a5f9e438d 100644 --- a/mozilla/string/public/nsCommonString.h +++ b/mozilla/string/public/nsCommonString.h @@ -21,6 +21,9 @@ * Scott Collins (original author) */ +/* nsCommonString.h --- a string implementation that shares its underlying storage */ + + #ifndef nsCommonString_h___ #define nsCommonString_h___ @@ -28,29 +31,72 @@ #include "nsAFlatString.h" #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif //-------1---------2---------3---------4---------5---------6---------7---------8 /** - * + * Not yet ready for non-|const| access */ -class nsCommonString +class NS_COM nsCommonString : public nsAFlatString { public: - // ... + typedef nsCommonString self_type; + typedef PRUnichar char_type; + typedef nsAString string_type; + + public: + nsCommonString() { } + nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#if 0 -class nsCommonCString +class NS_COM nsCommonCString : public nsAFlatCString { public: - // ... + typedef nsCommonCString self_type; + typedef char char_type; + typedef nsACString string_type; + + public: + nsCommonCString() { } + nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonCString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#endif #endif /* !defined(nsCommonString_h___) */ diff --git a/mozilla/string/public/nsDependentString.h b/mozilla/string/public/nsDependentString.h index 07b7d8fe84f..59bc4a94b3b 100644 --- a/mozilla/string/public/nsDependentString.h +++ b/mozilla/string/public/nsDependentString.h @@ -73,7 +73,8 @@ class NS_COM nsLocalString // nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK // ~nsLocalString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; @@ -112,7 +113,8 @@ class NS_COM nsLocalCString // nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK // ~nsLocalCString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; diff --git a/mozilla/string/public/nsDependentSubstring.h b/mozilla/string/public/nsDependentSubstring.h index 7a95646610d..afbe0890f59 100644 --- a/mozilla/string/public/nsDependentSubstring.h +++ b/mozilla/string/public/nsDependentSubstring.h @@ -28,10 +28,6 @@ #include "nsAString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif - #ifndef nsStringTraits_h___ #include "nsStringTraits.h" #endif diff --git a/mozilla/string/public/nsLocalString.h b/mozilla/string/public/nsLocalString.h index 07b7d8fe84f..59bc4a94b3b 100644 --- a/mozilla/string/public/nsLocalString.h +++ b/mozilla/string/public/nsLocalString.h @@ -73,7 +73,8 @@ class NS_COM nsLocalString // nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK // ~nsLocalString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; @@ -112,7 +113,8 @@ class NS_COM nsLocalCString // nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK // ~nsLocalCString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; diff --git a/mozilla/string/public/nsPrivateSharableString.h b/mozilla/string/public/nsPrivateSharableString.h index 755e7c062e8..51dd57cf064 100755 --- a/mozilla/string/public/nsPrivateSharableString.h +++ b/mozilla/string/public/nsPrivateSharableString.h @@ -44,6 +44,7 @@ class nsPrivateSharableString virtual ~nsPrivateSharableString() {} virtual PRUint32 GetImplementationFlags() const; + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const nsBufferHandle* GetBufferHandle() const; virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; @@ -62,6 +63,13 @@ nsPrivateSharableString::GetSharedBufferHandle() const return 0; } +template +const nsBufferHandle* +nsPrivateSharableString::GetFlatBufferHandle() const + { + return GetSharedBufferHandle(); + } + template const nsBufferHandle* nsPrivateSharableString::GetBufferHandle() const diff --git a/mozilla/string/public/nsPromiseFlatString.h b/mozilla/string/public/nsPromiseFlatString.h index 8ba72aa5be6..1c23bd05945 100644 --- a/mozilla/string/public/nsPromiseFlatString.h +++ b/mozilla/string/public/nsPromiseFlatString.h @@ -24,120 +24,127 @@ #ifndef nsPromiseFlatString_h___ #define nsPromiseFlatString_h___ -#ifndef nsStringTraits_h___ -#include "nsStringTraits.h" +#ifndef nsCommonString_h___ +#include "nsCommonString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif + /** + * WARNING: + * + * Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last resort, + * and this may be necessary when dealing with legacy or OS calls, but in general, + * requiring a zero-terminated contiguous hunk of characters kills many of the performance + * wins the string classes offer. Write your own code to use |nsA[C]String&|s for parameters. + * Write your string proccessing algorithms to exploit iterators. If you do this, you + * will benefit from being able to chain operations without copying or allocating and your + * code will be significantly more efficient. Remember, a function that takes an + * |const nsA[C]String&| can always be passed a raw character pointer by wrapping it (for free) + * in a |nsLocal[C]String|. But a function that takes a character pointer always has the + * potential to force allocation and copying. + * + * + * How to use it: + * + * Like all `promises', a |nsPromiseFlat[C]String| doesn't own the characters it promises. + * You must never use it to promise characters out of a string with a shorter lifespan. + * The typical use will be something like this + * + * SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD + * + * Here's a BAD use: + * + * const char* buffer = PromiseFlatCString(aCString).get(); + * SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer + * + * A |nsPromiseFlat[C]String| doesn't support non-|const| access (you can't use it to make + * changes back into the original string). To help you avoid that, the only way to make + * one is with the function |PromiseFlat[C]String|, which produce a |const| instance. + * ``What if I need to keep a promise around for a little while?'' you might ask. + * In that case, you can keep a reference, like so + * + * const nsPromiseFlatString& flat = PromiseFlatString(aString); + * // this reference holds the anonymous temporary alive, but remember, it must _still_ + * // have a lifetime shorter than that of |aString| + * + * SomeOSFunction(flat.get()); + * SomeOtherOSFunction(flat.get()); + * + * + * How does it work? + * + * A |nsPromiseFlat[C]String| is just a wrapper for another string. If you apply it to + * a string that happens to be flat, your promise is just a reference to that other string + * and all calls are forwarded through to it. If you apply it to a non-flat string, + * then a temporary flat string is created for you, by allocating and copying. In the unlikely + * event that you end up assigning the result into a sharing string (e.g., |nsCommon[C]String|), + * the right thing happens. + */ -//-------1---------2---------3---------4---------5---------6---------7---------8 - -#define kDefaultFlatStringSize 64 - -template -class basic_nsPromiseFlatString - : public nsStringTraits::abstract_flat_type +class NS_COM nsPromiseFlatString + : public nsAFlatString /* , public nsAPromiseString */ { - typedef typename nsStringTraits::abstract_string_type string_type; - typedef string_type::const_iterator const_iterator; + friend const nsPromiseFlatString PromiseFlatString( const nsAString& ); public: - explicit basic_nsPromiseFlatString( const string_type& ); - - virtual - ~basic_nsPromiseFlatString( ) - { - if (mOwnsBuffer) - nsMemory::Free((void*)mBuffer); - } - - virtual PRUint32 Length() const { return mLength; } - - virtual const CharT* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 = 0 ) const; - virtual CharT* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 = 0 ) { return 0; } - - virtual const CharT* get() const { return mBuffer; } - // eliminate this function after we correctly implement |GetBufferHandle| + nsPromiseFlatString( const nsPromiseFlatString& ); + virtual const PRUnichar* get() const; // this will be gone after we fix obsolete/nsString protected: - PRUint32 mLength; - const CharT* mBuffer; - PRBool mOwnsBuffer; - CharT mInlineBuffer[kDefaultFlatStringSize]; + nsPromiseFlatString() : mPromisedString(&mFlattenedString) { } + explicit nsPromiseFlatString( const nsAString& aString ); + + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + // NOT TO BE IMPLEMENTED + void operator=( const nsPromiseFlatString& ); + + private: + nsCommonString mFlattenedString; + const nsAFlatString* mPromisedString; }; -template -basic_nsPromiseFlatString::basic_nsPromiseFlatString( const string_type& aString ) - : mLength(aString.Length()), - mOwnsBuffer(PR_FALSE) +class NS_COM nsPromiseFlatCString + : public nsAFlatCString /* , public nsAPromiseCString */ { - typedef nsReadingIterator iterator; + friend const nsPromiseFlatCString PromiseFlatCString( const nsACString& ); - iterator start; - iterator end; - - aString.BeginReading(start); - aString.EndReading(end); + public: + nsPromiseFlatCString( const nsPromiseFlatCString& ); + virtual const char* get() const; // this will be gone after we fix obsolete/nsString - // First count the number of buffers - PRInt32 buffer_count = 0; - while ( start != end ) - { - buffer_count++; - start.advance(start.size_forward()); - } + protected: + nsPromiseFlatCString() : mPromisedString(&mFlattenedString) { } + explicit nsPromiseFlatCString( const nsACString& aString ); - // Now figure out what we want to do with the string - aString.BeginReading(start); - // XXX Not guaranteed null-termination in the first case - // If it's a single buffer, we just use the implementation's buffer - if ( buffer_count == 1 ) - mBuffer = start.get(); - // If it's too big for our inline buffer, we allocate a new one - else if ( mLength > kDefaultFlatStringSize-1 ) - { - CharT* result = NS_STATIC_CAST(CharT*, nsMemory::Alloc((mLength+1) * sizeof(CharT))); - CharT* toBegin = result; - *copy_string(start, end, toBegin) = CharT(0); + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; - mBuffer = result; - mOwnsBuffer = PR_TRUE; - } - // Otherwise copy into our internal buffer - else - { - mBuffer = mInlineBuffer; - CharT* toBegin = &mInlineBuffer[0]; - copy_string( start, end, toBegin); - mInlineBuffer[mLength] = 0; - } + private: + // NOT TO BE IMPLEMENTED + void operator=( const nsPromiseFlatCString& ); + + private: + nsCommonCString mFlattenedString; + const nsAFlatCString* mPromisedString; + }; + + +inline +const nsPromiseFlatString +PromiseFlatString( const nsAString& aString ) + { + return nsPromiseFlatString(aString); } - -template -const CharT* -basic_nsPromiseFlatString::GetReadableFragment( nsReadableFragment& aFragment, - nsFragmentRequest aRequest, - PRUint32 aOffset ) const +inline +const nsPromiseFlatCString +PromiseFlatCString( const nsACString& aString ) { - switch ( aRequest ) - { - case kFirstFragment: - case kLastFragment: - case kFragmentAt: - aFragment.mEnd = (aFragment.mStart = mBuffer) + mLength; - return aFragment.mStart + aOffset; - - case kPrevFragment: - case kNextFragment: - default: - return 0; - } + return nsPromiseFlatCString(aString); } -typedef basic_nsPromiseFlatString nsPromiseFlatString; -typedef basic_nsPromiseFlatString nsPromiseFlatCString; - #endif /* !defined(nsPromiseFlatString_h___) */ diff --git a/mozilla/string/public/nsPromiseSubstring.h b/mozilla/string/public/nsPromiseSubstring.h index 7a95646610d..afbe0890f59 100644 --- a/mozilla/string/public/nsPromiseSubstring.h +++ b/mozilla/string/public/nsPromiseSubstring.h @@ -28,10 +28,6 @@ #include "nsAString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif - #ifndef nsStringTraits_h___ #include "nsStringTraits.h" #endif diff --git a/mozilla/string/public/nsSharableString.h b/mozilla/string/public/nsSharableString.h index 3894c57b449..64a5f9e438d 100644 --- a/mozilla/string/public/nsSharableString.h +++ b/mozilla/string/public/nsSharableString.h @@ -21,6 +21,9 @@ * Scott Collins (original author) */ +/* nsCommonString.h --- a string implementation that shares its underlying storage */ + + #ifndef nsCommonString_h___ #define nsCommonString_h___ @@ -28,29 +31,72 @@ #include "nsAFlatString.h" #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif //-------1---------2---------3---------4---------5---------6---------7---------8 /** - * + * Not yet ready for non-|const| access */ -class nsCommonString +class NS_COM nsCommonString : public nsAFlatString { public: - // ... + typedef nsCommonString self_type; + typedef PRUnichar char_type; + typedef nsAString string_type; + + public: + nsCommonString() { } + nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#if 0 -class nsCommonCString +class NS_COM nsCommonCString : public nsAFlatCString { public: - // ... + typedef nsCommonCString self_type; + typedef char char_type; + typedef nsACString string_type; + + public: + nsCommonCString() { } + nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonCString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#endif #endif /* !defined(nsCommonString_h___) */ diff --git a/mozilla/string/public/nsStringTraits.h b/mozilla/string/public/nsStringTraits.h index b1f2b104b11..820a1c71ec2 100644 --- a/mozilla/string/public/nsStringTraits.h +++ b/mozilla/string/public/nsStringTraits.h @@ -30,6 +30,10 @@ #include "nsStringFwd.h" #endif +#ifndef nscore_h___ +#include "nscore.h" +#endif + diff --git a/mozilla/string/src/nsCommonString.cpp b/mozilla/string/src/nsCommonString.cpp index 90f6f5b6665..fefbba15917 100644 --- a/mozilla/string/src/nsCommonString.cpp +++ b/mozilla/string/src/nsCommonString.cpp @@ -24,4 +24,35 @@ //-------1---------2---------3---------4---------5---------6---------7---------8 #include "nsCommonString.h" +// #include "nsBufferHandleUtils.h" + +void +nsCommonString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } + +void +nsCommonCString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonCString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } diff --git a/mozilla/string/src/nsSharableString.cpp b/mozilla/string/src/nsSharableString.cpp index 90f6f5b6665..fefbba15917 100644 --- a/mozilla/string/src/nsSharableString.cpp +++ b/mozilla/string/src/nsSharableString.cpp @@ -24,4 +24,35 @@ //-------1---------2---------3---------4---------5---------6---------7---------8 #include "nsCommonString.h" +// #include "nsBufferHandleUtils.h" + +void +nsCommonString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } + +void +nsCommonCString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonCString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } diff --git a/mozilla/xpcom/string/macbuild/string.mcp b/mozilla/xpcom/string/macbuild/string.mcp index 43f759e387bcd71b3c9a11a7add300bf893bba37..8f2584ee852e8597665aec89e9ca9bb3ab23be68 100644 GIT binary patch delta 1591 zcmZ9MYiJx*6oBuYoqbI<*=+V{)=i>G+qJRTCe8*$?87{o;%X+@rhq>EBJX;)}zg@P2Z*5V&QeEf_4^M?kZ!g}uHOj5jX=9_cx zIrpA(=FI)+rg-a~7%Hl2g%IK(geD1%uM(Q@e-Vm$bwy-vWN$ck!s4*L_u0}2yzHUy z07(P#AWMWee<8#Jub{6K)y2x|FR9vWsjgOzmc|Pj%v*i}ynt}O6v!Spjvu+9i=cy~ z*-0s$<_a0$kKOz+$sbc7!ytA9vaRFJGW$)+PUK)V4>5g>G3AIhsf& z%DfgVm%VM5X%~wGPWzkP$qhN;W?!c0hDW5-uKP-B_bnW=YIJdmIalGgV=%Ki=?Vsmrf!dEt@+lyk? z!y)tXk-Qm*pPLOFQThwAqRrM)o4NAR|b5oxLQD6Hg(d$e2a; z{d>!?&GL$(R;u&gknm8Zgw)DrVdeo% z?1nAi1RSFEK6cGAp}Q;-Hup+|`?OjY53l=7!T$gE*}v|yWfn~Sp=M)k$?f6MVdQ;W z*$n<_gL>Rn<8Q3pI={hj0@aUdfK=b zrV(MS(OeDF4+Np*H`Ex7ba!@gA8@XNF{ES5*zMV@Cq{+at@br5nv)95xYxexo-5C%+0AZk!BNv4^x|OvAeCK-_XV JlAwRm{{RJQN4)?5 delta 1283 zcma)+OGs2v7{|}Kb9G+ojLztYGNU;@Mr)eUL7_$D;4>5(m60eg(S;59!m*+UIG`y6 zCAYH}BGlXkMwqv_i$Vw5MQRbW>4CHemu-?#&wQb=SzYLLBs7e%Sf!M>a}un)Ogtljd)=!bpOLe#OZ?LPUT zt&>up6b#B$`N}EgzUh!lhl2uZ=+4pq$h4~JUY6X^Z5O1Fp81TgrRE{_E!-xBs@Sjm zK^6|bW6$=B^xO0I3Au7dUg_(RuM zZkXkxNPFQl?5nu-Y-bBlhZK+*ND-+=W+IJ9Lt9Tc1ed~_kU4R6a3nGW!y^1#g)||L zBh8$A{ZbUNklDx_qy>2r=|cLDexwzdi}WCCkk!aMqzyRD51x-g8Pbb%Bg>H|GzZn` zqLciT=~LC=oJwRZvIJRyEIuw{2##U7F+Kn?g@Gn1dVQb z4|#e~jlQUYo={4TQIpU`w5D)l>9(|~G1chi^DrZAs?q10K!2fJcXLyd)-?G$O4%-J VO*Ojtvc^=SZ;dBScPi*l`VSih4%h$y diff --git a/mozilla/xpcom/string/obsolete/nsString.cpp b/mozilla/xpcom/string/obsolete/nsString.cpp index 2ec4f28fec5..2bad4c8dbb6 100644 --- a/mozilla/xpcom/string/obsolete/nsString.cpp +++ b/mozilla/xpcom/string/obsolete/nsString.cpp @@ -42,6 +42,11 @@ static const char* kPossibleNull = "Error: possible unintended null in string"; static const char* kNullPointerError = "Error: unexpected null ptr"; static const char* kWhitespace="\b\t\r\n "; +const nsBufferHandle* +nsCString::GetFlatBufferHandle() const + { + return NS_REINTERPRET_CAST(const nsBufferHandle*, 1); + } static void CSubsume(nsStr& aDest,nsStr& aSource){ if(aSource.mStr && aSource.mLength) { diff --git a/mozilla/xpcom/string/obsolete/nsString.h b/mozilla/xpcom/string/obsolete/nsString.h index 49f6c93a893..9bf13d1f692 100644 --- a/mozilla/xpcom/string/obsolete/nsString.h +++ b/mozilla/xpcom/string/obsolete/nsString.h @@ -70,6 +70,7 @@ class NS_COM nsCString : public nsStr { protected: + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const char* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual char* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ); diff --git a/mozilla/xpcom/string/obsolete/nsString2.cpp b/mozilla/xpcom/string/obsolete/nsString2.cpp index 50b06ab680a..78963ffea58 100644 --- a/mozilla/xpcom/string/obsolete/nsString2.cpp +++ b/mozilla/xpcom/string/obsolete/nsString2.cpp @@ -39,6 +39,13 @@ static const char* kPossibleNull = "Error: possible unintended null in string"; static const char* kNullPointerError = "Error: unexpected null ptr"; static const char* kWhitespace="\b\t\r\n "; +const nsBufferHandle* +nsString::GetFlatBufferHandle() const + { + return NS_REINTERPRET_CAST(const nsBufferHandle*, 1); + } + + static void Subsume(nsStr& aDest,nsStr& aSource){ if(aSource.mStr && aSource.mLength) { diff --git a/mozilla/xpcom/string/obsolete/nsString2.h b/mozilla/xpcom/string/obsolete/nsString2.h index a710d5ce255..d7698322cd2 100644 --- a/mozilla/xpcom/string/obsolete/nsString2.h +++ b/mozilla/xpcom/string/obsolete/nsString2.h @@ -73,6 +73,7 @@ class NS_COM nsString : public nsStr { protected: + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const PRUnichar* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual PRUnichar* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ); diff --git a/mozilla/xpcom/string/public/nsAPromiseString.h b/mozilla/xpcom/string/public/nsAPromiseString.h index 1c0885f9f27..70bb5187785 100644 --- a/mozilla/xpcom/string/public/nsAPromiseString.h +++ b/mozilla/xpcom/string/public/nsAPromiseString.h @@ -26,12 +26,10 @@ #ifndef nsAPromiseString_h___ #define nsAPromiseString_h___ -#ifndef nsAString_h___ -#include "nsAString.h" -#endif - /** + * Don't |#include| this file yourself. You will get it automatically if you need it. * + * Why is it a separate file? To make it easier to find the classes in your local tree. */ class NS_COM nsAPromiseString : public nsAString { }; diff --git a/mozilla/xpcom/string/public/nsBufferHandle.h b/mozilla/xpcom/string/public/nsBufferHandle.h index 89f284085fb..0cd7e1d547e 100755 --- a/mozilla/xpcom/string/public/nsBufferHandle.h +++ b/mozilla/xpcom/string/public/nsBufferHandle.h @@ -180,6 +180,14 @@ class nsSharedBufferHandle mFlags = kIsShared; } + nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT*, CharT*, PRBool isSingleAllocation ) + : nsBufferHandle(aDataStart, aDataEnd) + { + mFlags = kIsShared; + if ( isSingleAllocation ) + mFlags |= kIsSingleAllocationWithBuffer; + } + ~nsSharedBufferHandle(); void diff --git a/mozilla/xpcom/string/public/nsBufferHandleUtils.h b/mozilla/xpcom/string/public/nsBufferHandleUtils.h index ed09b164a39..565ac3b64f0 100644 --- a/mozilla/xpcom/string/public/nsBufferHandleUtils.h +++ b/mozilla/xpcom/string/public/nsBufferHandleUtils.h @@ -37,6 +37,71 @@ // for placement |new| +template +class nsAutoBufferHandle + { + public: + nsAutoBufferHandle() : mHandle(0) { } + + nsAutoBufferHandle( const nsAutoBufferHandle& aOther ) + : mHandle(aOther.get()) + { + if ( mHandle) + mHandle->AcquireReference(); + } + + explicit + nsAutoBufferHandle( const nsSharedBufferHandle* aHandle ) + : mHandle(aHandle) + { + if ( mHandle) + mHandle->AcquireReference(); + } + + ~nsAutoBufferHandle() + { + if ( mHandle ) + mHandle->ReleaseReference(); + } + + nsAutoBufferHandle& + operator=( const nsSharedBufferHandle* rhs ) + { + nsSharedBufferHandle* old_handle = mHandle; + if ( (mHandle = NS_CONST_CAST(nsSharedBufferHandle*, rhs)) ) + mHandle->AcquireReference(); + if ( old_handle ) + old_handle->ReleaseReference(); + return *this; + } + + nsAutoBufferHandle& + operator=( const nsAutoBufferHandle& rhs ) + { + return operator=(rhs.get()); + } + + nsSharedBufferHandle* + get() const + { + return mHandle; + } + + operator nsSharedBufferHandle*() const + { + return get(); + } + + nsSharedBufferHandle* + operator->() const + { + return get(); + } + + private: + nsSharedBufferHandle* mHandle; + }; + template inline diff --git a/mozilla/xpcom/string/public/nsCommonString.h b/mozilla/xpcom/string/public/nsCommonString.h index 3894c57b449..64a5f9e438d 100644 --- a/mozilla/xpcom/string/public/nsCommonString.h +++ b/mozilla/xpcom/string/public/nsCommonString.h @@ -21,6 +21,9 @@ * Scott Collins (original author) */ +/* nsCommonString.h --- a string implementation that shares its underlying storage */ + + #ifndef nsCommonString_h___ #define nsCommonString_h___ @@ -28,29 +31,72 @@ #include "nsAFlatString.h" #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif //-------1---------2---------3---------4---------5---------6---------7---------8 /** - * + * Not yet ready for non-|const| access */ -class nsCommonString +class NS_COM nsCommonString : public nsAFlatString { public: - // ... + typedef nsCommonString self_type; + typedef PRUnichar char_type; + typedef nsAString string_type; + + public: + nsCommonString() { } + nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#if 0 -class nsCommonCString +class NS_COM nsCommonCString : public nsAFlatCString { public: - // ... + typedef nsCommonCString self_type; + typedef char char_type; + typedef nsACString string_type; + + public: + nsCommonCString() { } + nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonCString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#endif #endif /* !defined(nsCommonString_h___) */ diff --git a/mozilla/xpcom/string/public/nsDependentString.h b/mozilla/xpcom/string/public/nsDependentString.h index 07b7d8fe84f..59bc4a94b3b 100644 --- a/mozilla/xpcom/string/public/nsDependentString.h +++ b/mozilla/xpcom/string/public/nsDependentString.h @@ -73,7 +73,8 @@ class NS_COM nsLocalString // nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK // ~nsLocalString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; @@ -112,7 +113,8 @@ class NS_COM nsLocalCString // nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK // ~nsLocalCString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; diff --git a/mozilla/xpcom/string/public/nsDependentSubstring.h b/mozilla/xpcom/string/public/nsDependentSubstring.h index 7a95646610d..afbe0890f59 100644 --- a/mozilla/xpcom/string/public/nsDependentSubstring.h +++ b/mozilla/xpcom/string/public/nsDependentSubstring.h @@ -28,10 +28,6 @@ #include "nsAString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif - #ifndef nsStringTraits_h___ #include "nsStringTraits.h" #endif diff --git a/mozilla/xpcom/string/public/nsLocalString.h b/mozilla/xpcom/string/public/nsLocalString.h index 07b7d8fe84f..59bc4a94b3b 100644 --- a/mozilla/xpcom/string/public/nsLocalString.h +++ b/mozilla/xpcom/string/public/nsLocalString.h @@ -73,7 +73,8 @@ class NS_COM nsLocalString // nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK // ~nsLocalString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; @@ -112,7 +113,8 @@ class NS_COM nsLocalCString // nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK // ~nsLocalCString(); // auto-generated destructor OK - virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetFlatBufferHandle() const { return &mHandle; } + virtual const nsBufferHandle* GetBufferHandle() const { return &mHandle; } private: nsBufferHandle mHandle; diff --git a/mozilla/xpcom/string/public/nsPrivateSharableString.h b/mozilla/xpcom/string/public/nsPrivateSharableString.h index 755e7c062e8..51dd57cf064 100755 --- a/mozilla/xpcom/string/public/nsPrivateSharableString.h +++ b/mozilla/xpcom/string/public/nsPrivateSharableString.h @@ -44,6 +44,7 @@ class nsPrivateSharableString virtual ~nsPrivateSharableString() {} virtual PRUint32 GetImplementationFlags() const; + virtual const nsBufferHandle* GetFlatBufferHandle() const; virtual const nsBufferHandle* GetBufferHandle() const; virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; @@ -62,6 +63,13 @@ nsPrivateSharableString::GetSharedBufferHandle() const return 0; } +template +const nsBufferHandle* +nsPrivateSharableString::GetFlatBufferHandle() const + { + return GetSharedBufferHandle(); + } + template const nsBufferHandle* nsPrivateSharableString::GetBufferHandle() const diff --git a/mozilla/xpcom/string/public/nsPromiseFlatString.h b/mozilla/xpcom/string/public/nsPromiseFlatString.h index 8ba72aa5be6..1c23bd05945 100644 --- a/mozilla/xpcom/string/public/nsPromiseFlatString.h +++ b/mozilla/xpcom/string/public/nsPromiseFlatString.h @@ -24,120 +24,127 @@ #ifndef nsPromiseFlatString_h___ #define nsPromiseFlatString_h___ -#ifndef nsStringTraits_h___ -#include "nsStringTraits.h" +#ifndef nsCommonString_h___ +#include "nsCommonString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif + /** + * WARNING: + * + * Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last resort, + * and this may be necessary when dealing with legacy or OS calls, but in general, + * requiring a zero-terminated contiguous hunk of characters kills many of the performance + * wins the string classes offer. Write your own code to use |nsA[C]String&|s for parameters. + * Write your string proccessing algorithms to exploit iterators. If you do this, you + * will benefit from being able to chain operations without copying or allocating and your + * code will be significantly more efficient. Remember, a function that takes an + * |const nsA[C]String&| can always be passed a raw character pointer by wrapping it (for free) + * in a |nsLocal[C]String|. But a function that takes a character pointer always has the + * potential to force allocation and copying. + * + * + * How to use it: + * + * Like all `promises', a |nsPromiseFlat[C]String| doesn't own the characters it promises. + * You must never use it to promise characters out of a string with a shorter lifespan. + * The typical use will be something like this + * + * SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD + * + * Here's a BAD use: + * + * const char* buffer = PromiseFlatCString(aCString).get(); + * SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer + * + * A |nsPromiseFlat[C]String| doesn't support non-|const| access (you can't use it to make + * changes back into the original string). To help you avoid that, the only way to make + * one is with the function |PromiseFlat[C]String|, which produce a |const| instance. + * ``What if I need to keep a promise around for a little while?'' you might ask. + * In that case, you can keep a reference, like so + * + * const nsPromiseFlatString& flat = PromiseFlatString(aString); + * // this reference holds the anonymous temporary alive, but remember, it must _still_ + * // have a lifetime shorter than that of |aString| + * + * SomeOSFunction(flat.get()); + * SomeOtherOSFunction(flat.get()); + * + * + * How does it work? + * + * A |nsPromiseFlat[C]String| is just a wrapper for another string. If you apply it to + * a string that happens to be flat, your promise is just a reference to that other string + * and all calls are forwarded through to it. If you apply it to a non-flat string, + * then a temporary flat string is created for you, by allocating and copying. In the unlikely + * event that you end up assigning the result into a sharing string (e.g., |nsCommon[C]String|), + * the right thing happens. + */ -//-------1---------2---------3---------4---------5---------6---------7---------8 - -#define kDefaultFlatStringSize 64 - -template -class basic_nsPromiseFlatString - : public nsStringTraits::abstract_flat_type +class NS_COM nsPromiseFlatString + : public nsAFlatString /* , public nsAPromiseString */ { - typedef typename nsStringTraits::abstract_string_type string_type; - typedef string_type::const_iterator const_iterator; + friend const nsPromiseFlatString PromiseFlatString( const nsAString& ); public: - explicit basic_nsPromiseFlatString( const string_type& ); - - virtual - ~basic_nsPromiseFlatString( ) - { - if (mOwnsBuffer) - nsMemory::Free((void*)mBuffer); - } - - virtual PRUint32 Length() const { return mLength; } - - virtual const CharT* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 = 0 ) const; - virtual CharT* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 = 0 ) { return 0; } - - virtual const CharT* get() const { return mBuffer; } - // eliminate this function after we correctly implement |GetBufferHandle| + nsPromiseFlatString( const nsPromiseFlatString& ); + virtual const PRUnichar* get() const; // this will be gone after we fix obsolete/nsString protected: - PRUint32 mLength; - const CharT* mBuffer; - PRBool mOwnsBuffer; - CharT mInlineBuffer[kDefaultFlatStringSize]; + nsPromiseFlatString() : mPromisedString(&mFlattenedString) { } + explicit nsPromiseFlatString( const nsAString& aString ); + + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + // NOT TO BE IMPLEMENTED + void operator=( const nsPromiseFlatString& ); + + private: + nsCommonString mFlattenedString; + const nsAFlatString* mPromisedString; }; -template -basic_nsPromiseFlatString::basic_nsPromiseFlatString( const string_type& aString ) - : mLength(aString.Length()), - mOwnsBuffer(PR_FALSE) +class NS_COM nsPromiseFlatCString + : public nsAFlatCString /* , public nsAPromiseCString */ { - typedef nsReadingIterator iterator; + friend const nsPromiseFlatCString PromiseFlatCString( const nsACString& ); - iterator start; - iterator end; - - aString.BeginReading(start); - aString.EndReading(end); + public: + nsPromiseFlatCString( const nsPromiseFlatCString& ); + virtual const char* get() const; // this will be gone after we fix obsolete/nsString - // First count the number of buffers - PRInt32 buffer_count = 0; - while ( start != end ) - { - buffer_count++; - start.advance(start.size_forward()); - } + protected: + nsPromiseFlatCString() : mPromisedString(&mFlattenedString) { } + explicit nsPromiseFlatCString( const nsACString& aString ); - // Now figure out what we want to do with the string - aString.BeginReading(start); - // XXX Not guaranteed null-termination in the first case - // If it's a single buffer, we just use the implementation's buffer - if ( buffer_count == 1 ) - mBuffer = start.get(); - // If it's too big for our inline buffer, we allocate a new one - else if ( mLength > kDefaultFlatStringSize-1 ) - { - CharT* result = NS_STATIC_CAST(CharT*, nsMemory::Alloc((mLength+1) * sizeof(CharT))); - CharT* toBegin = result; - *copy_string(start, end, toBegin) = CharT(0); + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; - mBuffer = result; - mOwnsBuffer = PR_TRUE; - } - // Otherwise copy into our internal buffer - else - { - mBuffer = mInlineBuffer; - CharT* toBegin = &mInlineBuffer[0]; - copy_string( start, end, toBegin); - mInlineBuffer[mLength] = 0; - } + private: + // NOT TO BE IMPLEMENTED + void operator=( const nsPromiseFlatCString& ); + + private: + nsCommonCString mFlattenedString; + const nsAFlatCString* mPromisedString; + }; + + +inline +const nsPromiseFlatString +PromiseFlatString( const nsAString& aString ) + { + return nsPromiseFlatString(aString); } - -template -const CharT* -basic_nsPromiseFlatString::GetReadableFragment( nsReadableFragment& aFragment, - nsFragmentRequest aRequest, - PRUint32 aOffset ) const +inline +const nsPromiseFlatCString +PromiseFlatCString( const nsACString& aString ) { - switch ( aRequest ) - { - case kFirstFragment: - case kLastFragment: - case kFragmentAt: - aFragment.mEnd = (aFragment.mStart = mBuffer) + mLength; - return aFragment.mStart + aOffset; - - case kPrevFragment: - case kNextFragment: - default: - return 0; - } + return nsPromiseFlatCString(aString); } -typedef basic_nsPromiseFlatString nsPromiseFlatString; -typedef basic_nsPromiseFlatString nsPromiseFlatCString; - #endif /* !defined(nsPromiseFlatString_h___) */ diff --git a/mozilla/xpcom/string/public/nsPromiseSubstring.h b/mozilla/xpcom/string/public/nsPromiseSubstring.h index 7a95646610d..afbe0890f59 100644 --- a/mozilla/xpcom/string/public/nsPromiseSubstring.h +++ b/mozilla/xpcom/string/public/nsPromiseSubstring.h @@ -28,10 +28,6 @@ #include "nsAString.h" #endif -#ifndef nsAPromiseString_h___ -#include "nsAPromiseString.h" -#endif - #ifndef nsStringTraits_h___ #include "nsStringTraits.h" #endif diff --git a/mozilla/xpcom/string/public/nsSharableString.h b/mozilla/xpcom/string/public/nsSharableString.h index 3894c57b449..64a5f9e438d 100644 --- a/mozilla/xpcom/string/public/nsSharableString.h +++ b/mozilla/xpcom/string/public/nsSharableString.h @@ -21,6 +21,9 @@ * Scott Collins (original author) */ +/* nsCommonString.h --- a string implementation that shares its underlying storage */ + + #ifndef nsCommonString_h___ #define nsCommonString_h___ @@ -28,29 +31,72 @@ #include "nsAFlatString.h" #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif //-------1---------2---------3---------4---------5---------6---------7---------8 /** - * + * Not yet ready for non-|const| access */ -class nsCommonString +class NS_COM nsCommonString : public nsAFlatString { public: - // ... + typedef nsCommonString self_type; + typedef PRUnichar char_type; + typedef nsAString string_type; + + public: + nsCommonString() { } + nsCommonString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#if 0 -class nsCommonCString +class NS_COM nsCommonCString : public nsAFlatCString { public: - // ... + typedef nsCommonCString self_type; + typedef char char_type; + typedef nsACString string_type; + + public: + nsCommonCString() { } + nsCommonCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { } + nsCommonCString( const string_type& aReadable ) { assign(aReadable); } + + self_type& + operator=( const string_type& aReadable ) + { + assign(aReadable); + return *this; + } + + protected: + void assign( const string_type& ); + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + + private: + nsAutoBufferHandle mBuffer; }; -#endif #endif /* !defined(nsCommonString_h___) */ diff --git a/mozilla/xpcom/string/public/nsStringTraits.h b/mozilla/xpcom/string/public/nsStringTraits.h index b1f2b104b11..820a1c71ec2 100644 --- a/mozilla/xpcom/string/public/nsStringTraits.h +++ b/mozilla/xpcom/string/public/nsStringTraits.h @@ -30,6 +30,10 @@ #include "nsStringFwd.h" #endif +#ifndef nscore_h___ +#include "nscore.h" +#endif + diff --git a/mozilla/xpcom/string/src/nsCommonString.cpp b/mozilla/xpcom/string/src/nsCommonString.cpp index 90f6f5b6665..fefbba15917 100644 --- a/mozilla/xpcom/string/src/nsCommonString.cpp +++ b/mozilla/xpcom/string/src/nsCommonString.cpp @@ -24,4 +24,35 @@ //-------1---------2---------3---------4---------5---------6---------7---------8 #include "nsCommonString.h" +// #include "nsBufferHandleUtils.h" + +void +nsCommonString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } + +void +nsCommonCString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonCString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } diff --git a/mozilla/xpcom/string/src/nsSharableString.cpp b/mozilla/xpcom/string/src/nsSharableString.cpp index 90f6f5b6665..fefbba15917 100644 --- a/mozilla/xpcom/string/src/nsSharableString.cpp +++ b/mozilla/xpcom/string/src/nsSharableString.cpp @@ -24,4 +24,35 @@ //-------1---------2---------3---------4---------5---------6---------7---------8 #include "nsCommonString.h" +// #include "nsBufferHandleUtils.h" + +void +nsCommonString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonString::GetSharedBufferHandle() const + { + return mBuffer.get(); + } + +void +nsCommonCString::assign( const string_type& aReadable ) + { + const nsSharedBufferHandle* handle = aReadable.GetSharedBufferHandle(); + if ( !handle ) + handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1); + mBuffer = handle; + } + +const nsSharedBufferHandle* +nsCommonCString::GetSharedBufferHandle() const + { + return mBuffer.get(); + }