From cdb32d5be10a53bda60706c223221ecdce5a037a Mon Sep 17 00:00:00 2001 From: "scc%netscape.com" Date: Wed, 22 Mar 2000 08:19:48 +0000 Subject: [PATCH] Made critical operations exploit chunky iterators. These files are not yet part of the build. git-svn-id: svn://10.0.0.236/trunk@63729 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/string/public/nsAReadableString.h | 139 +++++++++++++---- mozilla/string/public/nsAWritableString.h | 147 ++++++++++++++++-- mozilla/xpcom/ds/nsAReadableString.h | 139 +++++++++++++---- mozilla/xpcom/ds/nsAWritableString.h | 147 ++++++++++++++++-- .../xpcom/string/public/nsAReadableString.h | 139 +++++++++++++---- .../xpcom/string/public/nsAWritableString.h | 147 ++++++++++++++++-- 6 files changed, 723 insertions(+), 135 deletions(-) diff --git a/mozilla/string/public/nsAReadableString.h b/mozilla/string/public/nsAReadableString.h index cff5d04c67c..ef55352d4ac 100644 --- a/mozilla/string/public/nsAReadableString.h +++ b/mozilla/string/public/nsAReadableString.h @@ -90,11 +90,13 @@ class basic_nsAReadableString } }; + public: + virtual const void* Implementation() const; + enum FragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt }; - // Damn! Had to make |GetConstFragment| and |Implementation| public because the compilers suck. Should be protected. - virtual const char* Implementation() const; + // Damn! Had to make |GetConstFragment| public because the compilers suck. Should be protected. virtual const CharT* GetConstFragment( ConstFragment&, FragmentRequest, PRUint32 = 0 ) const = 0; friend class ConstIterator; @@ -147,11 +149,17 @@ class basic_nsAReadableString CharT - operator*() + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + ConstIterator& operator++() { @@ -186,17 +194,69 @@ class basic_nsAReadableString return result; } + const ConstFragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + ConstIterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + ConstIterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + // Damn again! Problems with templates made me implement comparisons as members. PRBool - operator==( const ConstIterator& rhs ) + operator==( const ConstIterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const ConstIterator& rhs ) + operator!=( const ConstIterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -339,7 +399,6 @@ class basic_nsAReadableString }; #define NS_DEF_1_STRING_COMPARISON_OPERATOR(comp, T1, T2) \ - template \ inline \ PRBool \ operator comp( T1 lhs, T2 rhs ) \ @@ -348,6 +407,14 @@ class basic_nsAReadableString } #define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(> , T1, T2) + +#define NS_DEF_NON_TEMPLATE_STRING_COMPARISON_OPERATORS(T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ @@ -395,7 +462,7 @@ basic_nsAReadableString::GetUnicode() const } template -const char* +const void* basic_nsAReadableString::Implementation() const { return 0; @@ -453,7 +520,22 @@ template PRUint32 basic_nsAReadableString::CountChar( CharT c ) const { +#if 1 return PRUint32(count(Begin(), End(), c)); +#else + PRUint32 result = 0; + PRUint32 lengthToExamine = Length(); + + ConstIterator iter( Begin() ); + for (;;) + { + PRUint32 lengthToExamineInThisFragment = iter.size_forward(); + result += PRUint32(count(iter.operator->(), iter.operator->()+lengthToExamineInThisFragment, c)); + if ( !(lengthToExamine -= lengthToExamineInThisFragment) ) + return result; + iter += lengthToExamineInThisFragment; + } +#endif } @@ -485,7 +567,7 @@ PRUint32 basic_nsAReadableString::Right( basic_nsAWritableString& aResult, PRUint32 aLengthToCopy ) const { PRUint32 myLength = Length(); - aLengthToCopy = min(myLength, aLengthToCopy); + aLengthToCopy = std::min(myLength, aLengthToCopy); aResult = Substring(*this, myLength-aLengthToCopy, aLengthToCopy); return aResult.Length(); } @@ -792,8 +874,8 @@ class nsPromiseSubstring public: nsPromiseSubstring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PRUint32 aLength ) : mString(aString), - mStartPos( min(aStartPos, aString.Length()) ), - mLength( min(aLength, aString.Length()-mStartPos) ) + mStartPos( std::min(aStartPos, aString.Length()) ), + mLength( std::min(aLength, aString.Length()-mStartPos) ) { // nothing else to do here } @@ -854,35 +936,36 @@ Substring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PR return nsPromiseSubstring(aString, aStartPos, aSubstringLength); } - template int Compare( const basic_nsAReadableString& lhs, const basic_nsAReadableString& rhs ) { - /* - If this turns out to be too slow (after measurement), there are two important modifications - 1) chunky iterators - 2) and then possibly use |char_traits::compare| - */ + if ( &lhs == &rhs ) + return 0; PRUint32 lLength = lhs.Length(); PRUint32 rLength = rhs.Length(); - PRUint32 lengthToCompare = min(lLength, rLength); + PRUint32 lengthToCompare = std::min(lLength, rLength); - typedef typename basic_nsAReadableString::ConstIterator ConstIterator; - ConstIterator lPos = lhs.Begin(); - ConstIterator lEnd = lhs.Begin(lengthToCompare); - ConstIterator rPos = rhs.Begin(); + basic_nsAReadableString::ConstIterator leftIter( lhs.Begin() ); + basic_nsAReadableString::ConstIterator rightIter( rhs.Begin() ); - while ( lPos != lEnd ) + for (;;) { - if ( *lPos < *rPos ) - return -1; - if ( *rPos < *lPos ) - return 1; + basic_nsAReadableString::ConstIterator::difference_type lengthAvailable = std::min(leftIter.size_forward(), rightIter.size_forward()); + // assert( lengthAvailable >= 0 ); - ++lPos; - ++rPos; + if ( lengthAvailable > lengthToCompare ) + lengthAvailable = lengthToCompare; + + if ( int result = std::char_traits::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) ) + return result; + + if ( !(lengthToCompare -= lengthAvailable) ) + break; + + leftIter += lengthAvailable; + rightIter += lengthAvailable; } if ( lLength < rLength ) diff --git a/mozilla/string/public/nsAWritableString.h b/mozilla/string/public/nsAWritableString.h index 3dbc52b1b52..2e9f662a729 100644 --- a/mozilla/string/public/nsAWritableString.h +++ b/mozilla/string/public/nsAWritableString.h @@ -71,8 +71,8 @@ class basic_nsAWritableString public: typedef ptrdiff_t difference_type; typedef CharT value_type; - typedef const CharT* pointer; - typedef const CharT& reference; + typedef CharT* pointer; + typedef CharT& reference; typedef bidirectional_iterator_tag iterator_category; private: @@ -113,12 +113,18 @@ class basic_nsAWritableString // Iterator& operator=( const Iterator& ); ...use default copy-assignment operator - CharT& - operator*() + reference + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + Iterator& operator++() { @@ -153,14 +159,66 @@ class basic_nsAWritableString return result; } + const Fragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + Iterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + Iterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + PRBool - operator==( const Iterator& rhs ) + operator==( const Iterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const Iterator& rhs ) + operator!=( const Iterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -207,11 +265,13 @@ class basic_nsAWritableString virtual void SetLength( PRUint32 ) = 0; - // ...a synonym for |SetLength()| void Truncate( PRUint32 aNewLength=0 ) { - SetLength(aNewLength); + NS_ASSERTION(aNewLength<=Length(), "Can't use |Truncate()| to make a string longer."); + + if ( aNewLength < Length() ) + SetLength(aNewLength); } @@ -229,7 +289,7 @@ class basic_nsAWritableString // void ReplaceSubstring( ... ); // void Trim( ... ); // void CompressSet( ... ); - // void CompareWhitespace( ... ); + // void CompressWhitespace( ... ); @@ -278,12 +338,59 @@ class basic_nsAWritableString NS_DEF_STRING_COMPARISONS(basic_nsAWritableString) +template +typename basic_nsAWritableString::Iterator +copy_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_forward(), result.size_forward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, last.operator->() - first.operator->()); + + // assert(lengthToCopy > 0); + + std::char_traits::copy(result.operator->(), first.operator->(), lengthToCopy); + + first += lengthToCopy; + result += lengthToCopy; + } + + return result; + } + +template +typename basic_nsAWritableString::Iterator +copy_backward_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + typename basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_backward(), result.size_backward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, first.operator->() - last.operator->()); + + std::char_traits::move(result.operator->(), first.operator->(), lengthToCopy); + + first -= lengthToCopy; + result -= lengthToCopy; + } + + return result; + } + + + + template void basic_nsAWritableString::Assign( const basic_nsAReadableString& rhs ) { SetLength(rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin()); + copy_chunky(rhs.Begin(), rhs.End(), Begin()); } template @@ -292,7 +399,7 @@ basic_nsAWritableString::Append( const basic_nsAReadableString& rh { PRUint32 oldLength = Length(); SetLength(oldLength + rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin(oldLength)); + copy_chunky(rhs.Begin(), rhs.End(), Begin(oldLength)); } template @@ -307,20 +414,24 @@ template void basic_nsAWritableString::Insert( const basic_nsAReadableString& aReadable, PRUint32 aPosition ) { + typedef typename basic_nsAReadableString readable_t; + PRUint32 oldLength = Length(); SetLength(oldLength + aReadable.Length()); if ( aPosition < oldLength ) - std::copy_backward(Begin(aPosition), Begin(oldLength), End()); + copy_backward_chunky(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End()); else aPosition = oldLength; - std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition)); + copy_chunky(aReadable.Begin(), aReadable.End(), Begin(aPosition)); } template void basic_nsAWritableString::Cut( PRUint32 cutStart, PRUint32 cutLength ) { - std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart)); + typedef typename basic_nsAReadableString readable_t; + + copy_chunky(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart)); SetLength(Length()-cutLength); } @@ -339,13 +450,15 @@ basic_nsAWritableString::Replace( PRUint32 cutStart, PRUint32 cutLength, PRUint32 newLength = oldLength - cutLength + replacementLength; + typedef typename basic_nsAReadableString readable_t; + if ( cutLength > replacementLength ) - std::copy(Begin(cutEnd), End(), Begin(replacementEnd)); + copy_chunky(readable_t::Begin(cutEnd), readable_t::End(), Begin(replacementEnd)); SetLength(newLength); if ( cutLength < replacementLength ) - std::copy_backward(Begin(cutEnd), Begin(oldLength), Begin(replacementEnd)); + copy_backward_chunky(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd)); - std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); + copy_chunky(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); } // operator>> diff --git a/mozilla/xpcom/ds/nsAReadableString.h b/mozilla/xpcom/ds/nsAReadableString.h index cff5d04c67c..ef55352d4ac 100644 --- a/mozilla/xpcom/ds/nsAReadableString.h +++ b/mozilla/xpcom/ds/nsAReadableString.h @@ -90,11 +90,13 @@ class basic_nsAReadableString } }; + public: + virtual const void* Implementation() const; + enum FragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt }; - // Damn! Had to make |GetConstFragment| and |Implementation| public because the compilers suck. Should be protected. - virtual const char* Implementation() const; + // Damn! Had to make |GetConstFragment| public because the compilers suck. Should be protected. virtual const CharT* GetConstFragment( ConstFragment&, FragmentRequest, PRUint32 = 0 ) const = 0; friend class ConstIterator; @@ -147,11 +149,17 @@ class basic_nsAReadableString CharT - operator*() + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + ConstIterator& operator++() { @@ -186,17 +194,69 @@ class basic_nsAReadableString return result; } + const ConstFragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + ConstIterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + ConstIterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + // Damn again! Problems with templates made me implement comparisons as members. PRBool - operator==( const ConstIterator& rhs ) + operator==( const ConstIterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const ConstIterator& rhs ) + operator!=( const ConstIterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -339,7 +399,6 @@ class basic_nsAReadableString }; #define NS_DEF_1_STRING_COMPARISON_OPERATOR(comp, T1, T2) \ - template \ inline \ PRBool \ operator comp( T1 lhs, T2 rhs ) \ @@ -348,6 +407,14 @@ class basic_nsAReadableString } #define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(> , T1, T2) + +#define NS_DEF_NON_TEMPLATE_STRING_COMPARISON_OPERATORS(T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ @@ -395,7 +462,7 @@ basic_nsAReadableString::GetUnicode() const } template -const char* +const void* basic_nsAReadableString::Implementation() const { return 0; @@ -453,7 +520,22 @@ template PRUint32 basic_nsAReadableString::CountChar( CharT c ) const { +#if 1 return PRUint32(count(Begin(), End(), c)); +#else + PRUint32 result = 0; + PRUint32 lengthToExamine = Length(); + + ConstIterator iter( Begin() ); + for (;;) + { + PRUint32 lengthToExamineInThisFragment = iter.size_forward(); + result += PRUint32(count(iter.operator->(), iter.operator->()+lengthToExamineInThisFragment, c)); + if ( !(lengthToExamine -= lengthToExamineInThisFragment) ) + return result; + iter += lengthToExamineInThisFragment; + } +#endif } @@ -485,7 +567,7 @@ PRUint32 basic_nsAReadableString::Right( basic_nsAWritableString& aResult, PRUint32 aLengthToCopy ) const { PRUint32 myLength = Length(); - aLengthToCopy = min(myLength, aLengthToCopy); + aLengthToCopy = std::min(myLength, aLengthToCopy); aResult = Substring(*this, myLength-aLengthToCopy, aLengthToCopy); return aResult.Length(); } @@ -792,8 +874,8 @@ class nsPromiseSubstring public: nsPromiseSubstring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PRUint32 aLength ) : mString(aString), - mStartPos( min(aStartPos, aString.Length()) ), - mLength( min(aLength, aString.Length()-mStartPos) ) + mStartPos( std::min(aStartPos, aString.Length()) ), + mLength( std::min(aLength, aString.Length()-mStartPos) ) { // nothing else to do here } @@ -854,35 +936,36 @@ Substring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PR return nsPromiseSubstring(aString, aStartPos, aSubstringLength); } - template int Compare( const basic_nsAReadableString& lhs, const basic_nsAReadableString& rhs ) { - /* - If this turns out to be too slow (after measurement), there are two important modifications - 1) chunky iterators - 2) and then possibly use |char_traits::compare| - */ + if ( &lhs == &rhs ) + return 0; PRUint32 lLength = lhs.Length(); PRUint32 rLength = rhs.Length(); - PRUint32 lengthToCompare = min(lLength, rLength); + PRUint32 lengthToCompare = std::min(lLength, rLength); - typedef typename basic_nsAReadableString::ConstIterator ConstIterator; - ConstIterator lPos = lhs.Begin(); - ConstIterator lEnd = lhs.Begin(lengthToCompare); - ConstIterator rPos = rhs.Begin(); + basic_nsAReadableString::ConstIterator leftIter( lhs.Begin() ); + basic_nsAReadableString::ConstIterator rightIter( rhs.Begin() ); - while ( lPos != lEnd ) + for (;;) { - if ( *lPos < *rPos ) - return -1; - if ( *rPos < *lPos ) - return 1; + basic_nsAReadableString::ConstIterator::difference_type lengthAvailable = std::min(leftIter.size_forward(), rightIter.size_forward()); + // assert( lengthAvailable >= 0 ); - ++lPos; - ++rPos; + if ( lengthAvailable > lengthToCompare ) + lengthAvailable = lengthToCompare; + + if ( int result = std::char_traits::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) ) + return result; + + if ( !(lengthToCompare -= lengthAvailable) ) + break; + + leftIter += lengthAvailable; + rightIter += lengthAvailable; } if ( lLength < rLength ) diff --git a/mozilla/xpcom/ds/nsAWritableString.h b/mozilla/xpcom/ds/nsAWritableString.h index 3dbc52b1b52..2e9f662a729 100644 --- a/mozilla/xpcom/ds/nsAWritableString.h +++ b/mozilla/xpcom/ds/nsAWritableString.h @@ -71,8 +71,8 @@ class basic_nsAWritableString public: typedef ptrdiff_t difference_type; typedef CharT value_type; - typedef const CharT* pointer; - typedef const CharT& reference; + typedef CharT* pointer; + typedef CharT& reference; typedef bidirectional_iterator_tag iterator_category; private: @@ -113,12 +113,18 @@ class basic_nsAWritableString // Iterator& operator=( const Iterator& ); ...use default copy-assignment operator - CharT& - operator*() + reference + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + Iterator& operator++() { @@ -153,14 +159,66 @@ class basic_nsAWritableString return result; } + const Fragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + Iterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + Iterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + PRBool - operator==( const Iterator& rhs ) + operator==( const Iterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const Iterator& rhs ) + operator!=( const Iterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -207,11 +265,13 @@ class basic_nsAWritableString virtual void SetLength( PRUint32 ) = 0; - // ...a synonym for |SetLength()| void Truncate( PRUint32 aNewLength=0 ) { - SetLength(aNewLength); + NS_ASSERTION(aNewLength<=Length(), "Can't use |Truncate()| to make a string longer."); + + if ( aNewLength < Length() ) + SetLength(aNewLength); } @@ -229,7 +289,7 @@ class basic_nsAWritableString // void ReplaceSubstring( ... ); // void Trim( ... ); // void CompressSet( ... ); - // void CompareWhitespace( ... ); + // void CompressWhitespace( ... ); @@ -278,12 +338,59 @@ class basic_nsAWritableString NS_DEF_STRING_COMPARISONS(basic_nsAWritableString) +template +typename basic_nsAWritableString::Iterator +copy_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_forward(), result.size_forward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, last.operator->() - first.operator->()); + + // assert(lengthToCopy > 0); + + std::char_traits::copy(result.operator->(), first.operator->(), lengthToCopy); + + first += lengthToCopy; + result += lengthToCopy; + } + + return result; + } + +template +typename basic_nsAWritableString::Iterator +copy_backward_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + typename basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_backward(), result.size_backward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, first.operator->() - last.operator->()); + + std::char_traits::move(result.operator->(), first.operator->(), lengthToCopy); + + first -= lengthToCopy; + result -= lengthToCopy; + } + + return result; + } + + + + template void basic_nsAWritableString::Assign( const basic_nsAReadableString& rhs ) { SetLength(rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin()); + copy_chunky(rhs.Begin(), rhs.End(), Begin()); } template @@ -292,7 +399,7 @@ basic_nsAWritableString::Append( const basic_nsAReadableString& rh { PRUint32 oldLength = Length(); SetLength(oldLength + rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin(oldLength)); + copy_chunky(rhs.Begin(), rhs.End(), Begin(oldLength)); } template @@ -307,20 +414,24 @@ template void basic_nsAWritableString::Insert( const basic_nsAReadableString& aReadable, PRUint32 aPosition ) { + typedef typename basic_nsAReadableString readable_t; + PRUint32 oldLength = Length(); SetLength(oldLength + aReadable.Length()); if ( aPosition < oldLength ) - std::copy_backward(Begin(aPosition), Begin(oldLength), End()); + copy_backward_chunky(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End()); else aPosition = oldLength; - std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition)); + copy_chunky(aReadable.Begin(), aReadable.End(), Begin(aPosition)); } template void basic_nsAWritableString::Cut( PRUint32 cutStart, PRUint32 cutLength ) { - std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart)); + typedef typename basic_nsAReadableString readable_t; + + copy_chunky(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart)); SetLength(Length()-cutLength); } @@ -339,13 +450,15 @@ basic_nsAWritableString::Replace( PRUint32 cutStart, PRUint32 cutLength, PRUint32 newLength = oldLength - cutLength + replacementLength; + typedef typename basic_nsAReadableString readable_t; + if ( cutLength > replacementLength ) - std::copy(Begin(cutEnd), End(), Begin(replacementEnd)); + copy_chunky(readable_t::Begin(cutEnd), readable_t::End(), Begin(replacementEnd)); SetLength(newLength); if ( cutLength < replacementLength ) - std::copy_backward(Begin(cutEnd), Begin(oldLength), Begin(replacementEnd)); + copy_backward_chunky(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd)); - std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); + copy_chunky(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); } // operator>> diff --git a/mozilla/xpcom/string/public/nsAReadableString.h b/mozilla/xpcom/string/public/nsAReadableString.h index cff5d04c67c..ef55352d4ac 100644 --- a/mozilla/xpcom/string/public/nsAReadableString.h +++ b/mozilla/xpcom/string/public/nsAReadableString.h @@ -90,11 +90,13 @@ class basic_nsAReadableString } }; + public: + virtual const void* Implementation() const; + enum FragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt }; - // Damn! Had to make |GetConstFragment| and |Implementation| public because the compilers suck. Should be protected. - virtual const char* Implementation() const; + // Damn! Had to make |GetConstFragment| public because the compilers suck. Should be protected. virtual const CharT* GetConstFragment( ConstFragment&, FragmentRequest, PRUint32 = 0 ) const = 0; friend class ConstIterator; @@ -147,11 +149,17 @@ class basic_nsAReadableString CharT - operator*() + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + ConstIterator& operator++() { @@ -186,17 +194,69 @@ class basic_nsAReadableString return result; } + const ConstFragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + ConstIterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + ConstIterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + // Damn again! Problems with templates made me implement comparisons as members. PRBool - operator==( const ConstIterator& rhs ) + operator==( const ConstIterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const ConstIterator& rhs ) + operator!=( const ConstIterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -339,7 +399,6 @@ class basic_nsAReadableString }; #define NS_DEF_1_STRING_COMPARISON_OPERATOR(comp, T1, T2) \ - template \ inline \ PRBool \ operator comp( T1 lhs, T2 rhs ) \ @@ -348,6 +407,14 @@ class basic_nsAReadableString } #define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \ + template NS_DEF_1_STRING_COMPARISON_OPERATOR(> , T1, T2) + +#define NS_DEF_NON_TEMPLATE_STRING_COMPARISON_OPERATORS(T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \ NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \ @@ -395,7 +462,7 @@ basic_nsAReadableString::GetUnicode() const } template -const char* +const void* basic_nsAReadableString::Implementation() const { return 0; @@ -453,7 +520,22 @@ template PRUint32 basic_nsAReadableString::CountChar( CharT c ) const { +#if 1 return PRUint32(count(Begin(), End(), c)); +#else + PRUint32 result = 0; + PRUint32 lengthToExamine = Length(); + + ConstIterator iter( Begin() ); + for (;;) + { + PRUint32 lengthToExamineInThisFragment = iter.size_forward(); + result += PRUint32(count(iter.operator->(), iter.operator->()+lengthToExamineInThisFragment, c)); + if ( !(lengthToExamine -= lengthToExamineInThisFragment) ) + return result; + iter += lengthToExamineInThisFragment; + } +#endif } @@ -485,7 +567,7 @@ PRUint32 basic_nsAReadableString::Right( basic_nsAWritableString& aResult, PRUint32 aLengthToCopy ) const { PRUint32 myLength = Length(); - aLengthToCopy = min(myLength, aLengthToCopy); + aLengthToCopy = std::min(myLength, aLengthToCopy); aResult = Substring(*this, myLength-aLengthToCopy, aLengthToCopy); return aResult.Length(); } @@ -792,8 +874,8 @@ class nsPromiseSubstring public: nsPromiseSubstring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PRUint32 aLength ) : mString(aString), - mStartPos( min(aStartPos, aString.Length()) ), - mLength( min(aLength, aString.Length()-mStartPos) ) + mStartPos( std::min(aStartPos, aString.Length()) ), + mLength( std::min(aLength, aString.Length()-mStartPos) ) { // nothing else to do here } @@ -854,35 +936,36 @@ Substring( const basic_nsAReadableString& aString, PRUint32 aStartPos, PR return nsPromiseSubstring(aString, aStartPos, aSubstringLength); } - template int Compare( const basic_nsAReadableString& lhs, const basic_nsAReadableString& rhs ) { - /* - If this turns out to be too slow (after measurement), there are two important modifications - 1) chunky iterators - 2) and then possibly use |char_traits::compare| - */ + if ( &lhs == &rhs ) + return 0; PRUint32 lLength = lhs.Length(); PRUint32 rLength = rhs.Length(); - PRUint32 lengthToCompare = min(lLength, rLength); + PRUint32 lengthToCompare = std::min(lLength, rLength); - typedef typename basic_nsAReadableString::ConstIterator ConstIterator; - ConstIterator lPos = lhs.Begin(); - ConstIterator lEnd = lhs.Begin(lengthToCompare); - ConstIterator rPos = rhs.Begin(); + basic_nsAReadableString::ConstIterator leftIter( lhs.Begin() ); + basic_nsAReadableString::ConstIterator rightIter( rhs.Begin() ); - while ( lPos != lEnd ) + for (;;) { - if ( *lPos < *rPos ) - return -1; - if ( *rPos < *lPos ) - return 1; + basic_nsAReadableString::ConstIterator::difference_type lengthAvailable = std::min(leftIter.size_forward(), rightIter.size_forward()); + // assert( lengthAvailable >= 0 ); - ++lPos; - ++rPos; + if ( lengthAvailable > lengthToCompare ) + lengthAvailable = lengthToCompare; + + if ( int result = std::char_traits::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) ) + return result; + + if ( !(lengthToCompare -= lengthAvailable) ) + break; + + leftIter += lengthAvailable; + rightIter += lengthAvailable; } if ( lLength < rLength ) diff --git a/mozilla/xpcom/string/public/nsAWritableString.h b/mozilla/xpcom/string/public/nsAWritableString.h index 3dbc52b1b52..2e9f662a729 100644 --- a/mozilla/xpcom/string/public/nsAWritableString.h +++ b/mozilla/xpcom/string/public/nsAWritableString.h @@ -71,8 +71,8 @@ class basic_nsAWritableString public: typedef ptrdiff_t difference_type; typedef CharT value_type; - typedef const CharT* pointer; - typedef const CharT& reference; + typedef CharT* pointer; + typedef CharT& reference; typedef bidirectional_iterator_tag iterator_category; private: @@ -113,12 +113,18 @@ class basic_nsAWritableString // Iterator& operator=( const Iterator& ); ...use default copy-assignment operator - CharT& - operator*() + reference + operator*() const { return *mPosition; } + pointer + operator->() const + { + return mPosition; + } + Iterator& operator++() { @@ -153,14 +159,66 @@ class basic_nsAWritableString return result; } + const Fragment& + fragment() const + { + return mFragment; + } + + difference_type + size_forward() const + { + return mFragment.mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mFragment.mStart; + } + + Iterator& + operator+=( difference_type n ) + { + if ( n < 0 ) + return operator-=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_forward()); + mPosition += one_hop; + normalize_forward(); + n -= one_hop; + } + + return *this; + } + + Iterator& + operator-=( difference_type n ) + { + if ( n < 0 ) + return operator+=(-n); + + while ( n ) + { + difference_type one_hop = std::min(n, size_backward()); + mPosition -= one_hop; + normalize_backward(); + n -= one_hop; + } + + return *this; + } + PRBool - operator==( const Iterator& rhs ) + operator==( const Iterator& rhs ) const { return mPosition == rhs.mPosition; } PRBool - operator!=( const Iterator& rhs ) + operator!=( const Iterator& rhs ) const { return mPosition != rhs.mPosition; } @@ -207,11 +265,13 @@ class basic_nsAWritableString virtual void SetLength( PRUint32 ) = 0; - // ...a synonym for |SetLength()| void Truncate( PRUint32 aNewLength=0 ) { - SetLength(aNewLength); + NS_ASSERTION(aNewLength<=Length(), "Can't use |Truncate()| to make a string longer."); + + if ( aNewLength < Length() ) + SetLength(aNewLength); } @@ -229,7 +289,7 @@ class basic_nsAWritableString // void ReplaceSubstring( ... ); // void Trim( ... ); // void CompressSet( ... ); - // void CompareWhitespace( ... ); + // void CompressWhitespace( ... ); @@ -278,12 +338,59 @@ class basic_nsAWritableString NS_DEF_STRING_COMPARISONS(basic_nsAWritableString) +template +typename basic_nsAWritableString::Iterator +copy_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_forward(), result.size_forward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, last.operator->() - first.operator->()); + + // assert(lengthToCopy > 0); + + std::char_traits::copy(result.operator->(), first.operator->(), lengthToCopy); + + first += lengthToCopy; + result += lengthToCopy; + } + + return result; + } + +template +typename basic_nsAWritableString::Iterator +copy_backward_chunky( typename basic_nsAReadableString::ConstIterator first, + typename basic_nsAReadableString::ConstIterator last, + typename basic_nsAWritableString::Iterator result ) + { + while ( first != last ) + { + typename basic_nsAReadableString::ConstIterator::difference_type lengthToCopy = std::min(first.size_backward(), result.size_backward()); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = std::min(lengthToCopy, first.operator->() - last.operator->()); + + std::char_traits::move(result.operator->(), first.operator->(), lengthToCopy); + + first -= lengthToCopy; + result -= lengthToCopy; + } + + return result; + } + + + + template void basic_nsAWritableString::Assign( const basic_nsAReadableString& rhs ) { SetLength(rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin()); + copy_chunky(rhs.Begin(), rhs.End(), Begin()); } template @@ -292,7 +399,7 @@ basic_nsAWritableString::Append( const basic_nsAReadableString& rh { PRUint32 oldLength = Length(); SetLength(oldLength + rhs.Length()); - std::copy(rhs.Begin(), rhs.End(), Begin(oldLength)); + copy_chunky(rhs.Begin(), rhs.End(), Begin(oldLength)); } template @@ -307,20 +414,24 @@ template void basic_nsAWritableString::Insert( const basic_nsAReadableString& aReadable, PRUint32 aPosition ) { + typedef typename basic_nsAReadableString readable_t; + PRUint32 oldLength = Length(); SetLength(oldLength + aReadable.Length()); if ( aPosition < oldLength ) - std::copy_backward(Begin(aPosition), Begin(oldLength), End()); + copy_backward_chunky(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End()); else aPosition = oldLength; - std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition)); + copy_chunky(aReadable.Begin(), aReadable.End(), Begin(aPosition)); } template void basic_nsAWritableString::Cut( PRUint32 cutStart, PRUint32 cutLength ) { - std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart)); + typedef typename basic_nsAReadableString readable_t; + + copy_chunky(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart)); SetLength(Length()-cutLength); } @@ -339,13 +450,15 @@ basic_nsAWritableString::Replace( PRUint32 cutStart, PRUint32 cutLength, PRUint32 newLength = oldLength - cutLength + replacementLength; + typedef typename basic_nsAReadableString readable_t; + if ( cutLength > replacementLength ) - std::copy(Begin(cutEnd), End(), Begin(replacementEnd)); + copy_chunky(readable_t::Begin(cutEnd), readable_t::End(), Begin(replacementEnd)); SetLength(newLength); if ( cutLength < replacementLength ) - std::copy_backward(Begin(cutEnd), Begin(oldLength), Begin(replacementEnd)); + copy_backward_chunky(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd)); - std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); + copy_chunky(aReplacement.Begin(), aReplacement.End(), Begin(cutStart)); } // operator>>