Made critical operations exploit chunky iterators. These files are not yet part of the build.

This commit is contained in:
scc%netscape.com 2000-03-22 08:19:48 +00:00
Родитель 08dd4f1cdc
Коммит 09052fa5c9
6 изменённых файлов: 723 добавлений и 135 удалений

Просмотреть файл

@ -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 <class CharT> \
inline \
PRBool \
operator comp( T1 lhs, T2 rhs ) \
@ -348,6 +407,14 @@ class basic_nsAReadableString
}
#define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \
template <class CharT> 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<PRUnichar>::GetUnicode() const
}
template <class CharT>
const char*
const void*
basic_nsAReadableString<CharT>::Implementation() const
{
return 0;
@ -453,7 +520,22 @@ template <class CharT>
PRUint32
basic_nsAReadableString<CharT>::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<CharT>::Right( basic_nsAWritableString<CharT>& 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<CharT>& 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<CharT>& aString, PRUint32 aStartPos, PR
return nsPromiseSubstring<CharT>(aString, aStartPos, aSubstringLength);
}
template <class CharT>
int
Compare( const basic_nsAReadableString<CharT>& lhs, const basic_nsAReadableString<CharT>& 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<T>::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<CharT>::ConstIterator ConstIterator;
ConstIterator lPos = lhs.Begin();
ConstIterator lEnd = lhs.Begin(lengthToCompare);
ConstIterator rPos = rhs.Begin();
basic_nsAReadableString<CharT>::ConstIterator leftIter( lhs.Begin() );
basic_nsAReadableString<CharT>::ConstIterator rightIter( rhs.Begin() );
while ( lPos != lEnd )
for (;;)
{
if ( *lPos < *rPos )
return -1;
if ( *rPos < *lPos )
return 1;
basic_nsAReadableString<CharT>::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<CharT>::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter += lengthAvailable;
rightIter += lengthAvailable;
}
if ( lLength < rLength )

Просмотреть файл

@ -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<CharT>)
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
basic_nsAReadableString<CharT>::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<CharT>::copy(result.operator->(), first.operator->(), lengthToCopy);
first += lengthToCopy;
result += lengthToCopy;
}
return result;
}
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_backward_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
typename basic_nsAReadableString<CharT>::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<CharT>::move(result.operator->(), first.operator->(), lengthToCopy);
first -= lengthToCopy;
result -= lengthToCopy;
}
return result;
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Assign( const basic_nsAReadableString<CharT>& rhs )
{
SetLength(rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin());
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin());
}
template <class CharT>
@ -292,7 +399,7 @@ basic_nsAWritableString<CharT>::Append( const basic_nsAReadableString<CharT>& rh
{
PRUint32 oldLength = Length();
SetLength(oldLength + rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin(oldLength));
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin(oldLength));
}
template <class CharT>
@ -307,20 +414,24 @@ template <class CharT>
void
basic_nsAWritableString<CharT>::Insert( const basic_nsAReadableString<CharT>& aReadable, PRUint32 aPosition )
{
typedef typename basic_nsAReadableString<CharT> readable_t;
PRUint32 oldLength = Length();
SetLength(oldLength + aReadable.Length());
if ( aPosition < oldLength )
std::copy_backward(Begin(aPosition), Begin(oldLength), End());
copy_backward_chunky<CharT>(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End());
else
aPosition = oldLength;
std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition));
copy_chunky<CharT>(aReadable.Begin(), aReadable.End(), Begin(aPosition));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
{
std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart));
typedef typename basic_nsAReadableString<CharT> readable_t;
copy_chunky<CharT>(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart));
SetLength(Length()-cutLength);
}
@ -339,13 +450,15 @@ basic_nsAWritableString<CharT>::Replace( PRUint32 cutStart, PRUint32 cutLength,
PRUint32 newLength = oldLength - cutLength + replacementLength;
typedef typename basic_nsAReadableString<CharT> readable_t;
if ( cutLength > replacementLength )
std::copy(Begin(cutEnd), End(), Begin(replacementEnd));
copy_chunky<CharT>(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<CharT>(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd));
std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
copy_chunky<CharT>(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
}
// operator>>

Просмотреть файл

@ -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 <class CharT> \
inline \
PRBool \
operator comp( T1 lhs, T2 rhs ) \
@ -348,6 +407,14 @@ class basic_nsAReadableString
}
#define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \
template <class CharT> 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<PRUnichar>::GetUnicode() const
}
template <class CharT>
const char*
const void*
basic_nsAReadableString<CharT>::Implementation() const
{
return 0;
@ -453,7 +520,22 @@ template <class CharT>
PRUint32
basic_nsAReadableString<CharT>::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<CharT>::Right( basic_nsAWritableString<CharT>& 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<CharT>& 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<CharT>& aString, PRUint32 aStartPos, PR
return nsPromiseSubstring<CharT>(aString, aStartPos, aSubstringLength);
}
template <class CharT>
int
Compare( const basic_nsAReadableString<CharT>& lhs, const basic_nsAReadableString<CharT>& 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<T>::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<CharT>::ConstIterator ConstIterator;
ConstIterator lPos = lhs.Begin();
ConstIterator lEnd = lhs.Begin(lengthToCompare);
ConstIterator rPos = rhs.Begin();
basic_nsAReadableString<CharT>::ConstIterator leftIter( lhs.Begin() );
basic_nsAReadableString<CharT>::ConstIterator rightIter( rhs.Begin() );
while ( lPos != lEnd )
for (;;)
{
if ( *lPos < *rPos )
return -1;
if ( *rPos < *lPos )
return 1;
basic_nsAReadableString<CharT>::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<CharT>::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter += lengthAvailable;
rightIter += lengthAvailable;
}
if ( lLength < rLength )

Просмотреть файл

@ -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<CharT>)
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
basic_nsAReadableString<CharT>::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<CharT>::copy(result.operator->(), first.operator->(), lengthToCopy);
first += lengthToCopy;
result += lengthToCopy;
}
return result;
}
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_backward_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
typename basic_nsAReadableString<CharT>::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<CharT>::move(result.operator->(), first.operator->(), lengthToCopy);
first -= lengthToCopy;
result -= lengthToCopy;
}
return result;
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Assign( const basic_nsAReadableString<CharT>& rhs )
{
SetLength(rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin());
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin());
}
template <class CharT>
@ -292,7 +399,7 @@ basic_nsAWritableString<CharT>::Append( const basic_nsAReadableString<CharT>& rh
{
PRUint32 oldLength = Length();
SetLength(oldLength + rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin(oldLength));
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin(oldLength));
}
template <class CharT>
@ -307,20 +414,24 @@ template <class CharT>
void
basic_nsAWritableString<CharT>::Insert( const basic_nsAReadableString<CharT>& aReadable, PRUint32 aPosition )
{
typedef typename basic_nsAReadableString<CharT> readable_t;
PRUint32 oldLength = Length();
SetLength(oldLength + aReadable.Length());
if ( aPosition < oldLength )
std::copy_backward(Begin(aPosition), Begin(oldLength), End());
copy_backward_chunky<CharT>(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End());
else
aPosition = oldLength;
std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition));
copy_chunky<CharT>(aReadable.Begin(), aReadable.End(), Begin(aPosition));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
{
std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart));
typedef typename basic_nsAReadableString<CharT> readable_t;
copy_chunky<CharT>(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart));
SetLength(Length()-cutLength);
}
@ -339,13 +450,15 @@ basic_nsAWritableString<CharT>::Replace( PRUint32 cutStart, PRUint32 cutLength,
PRUint32 newLength = oldLength - cutLength + replacementLength;
typedef typename basic_nsAReadableString<CharT> readable_t;
if ( cutLength > replacementLength )
std::copy(Begin(cutEnd), End(), Begin(replacementEnd));
copy_chunky<CharT>(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<CharT>(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd));
std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
copy_chunky<CharT>(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
}
// operator>>

Просмотреть файл

@ -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 <class CharT> \
inline \
PRBool \
operator comp( T1 lhs, T2 rhs ) \
@ -348,6 +407,14 @@ class basic_nsAReadableString
}
#define NS_DEF_STRING_COMPARISON_OPERATORS(T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(!=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(< , T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(<=, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(==, T1, T2) \
template <class CharT> NS_DEF_1_STRING_COMPARISON_OPERATOR(>=, T1, T2) \
template <class CharT> 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<PRUnichar>::GetUnicode() const
}
template <class CharT>
const char*
const void*
basic_nsAReadableString<CharT>::Implementation() const
{
return 0;
@ -453,7 +520,22 @@ template <class CharT>
PRUint32
basic_nsAReadableString<CharT>::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<CharT>::Right( basic_nsAWritableString<CharT>& 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<CharT>& 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<CharT>& aString, PRUint32 aStartPos, PR
return nsPromiseSubstring<CharT>(aString, aStartPos, aSubstringLength);
}
template <class CharT>
int
Compare( const basic_nsAReadableString<CharT>& lhs, const basic_nsAReadableString<CharT>& 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<T>::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<CharT>::ConstIterator ConstIterator;
ConstIterator lPos = lhs.Begin();
ConstIterator lEnd = lhs.Begin(lengthToCompare);
ConstIterator rPos = rhs.Begin();
basic_nsAReadableString<CharT>::ConstIterator leftIter( lhs.Begin() );
basic_nsAReadableString<CharT>::ConstIterator rightIter( rhs.Begin() );
while ( lPos != lEnd )
for (;;)
{
if ( *lPos < *rPos )
return -1;
if ( *rPos < *lPos )
return 1;
basic_nsAReadableString<CharT>::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<CharT>::compare(leftIter.operator->(), rightIter.operator->(), lengthAvailable) )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter += lengthAvailable;
rightIter += lengthAvailable;
}
if ( lLength < rLength )

Просмотреть файл

@ -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<CharT>)
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
basic_nsAReadableString<CharT>::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<CharT>::copy(result.operator->(), first.operator->(), lengthToCopy);
first += lengthToCopy;
result += lengthToCopy;
}
return result;
}
template <class CharT>
typename basic_nsAWritableString<CharT>::Iterator
copy_backward_chunky( typename basic_nsAReadableString<CharT>::ConstIterator first,
typename basic_nsAReadableString<CharT>::ConstIterator last,
typename basic_nsAWritableString<CharT>::Iterator result )
{
while ( first != last )
{
typename basic_nsAReadableString<CharT>::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<CharT>::move(result.operator->(), first.operator->(), lengthToCopy);
first -= lengthToCopy;
result -= lengthToCopy;
}
return result;
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Assign( const basic_nsAReadableString<CharT>& rhs )
{
SetLength(rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin());
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin());
}
template <class CharT>
@ -292,7 +399,7 @@ basic_nsAWritableString<CharT>::Append( const basic_nsAReadableString<CharT>& rh
{
PRUint32 oldLength = Length();
SetLength(oldLength + rhs.Length());
std::copy(rhs.Begin(), rhs.End(), Begin(oldLength));
copy_chunky<CharT>(rhs.Begin(), rhs.End(), Begin(oldLength));
}
template <class CharT>
@ -307,20 +414,24 @@ template <class CharT>
void
basic_nsAWritableString<CharT>::Insert( const basic_nsAReadableString<CharT>& aReadable, PRUint32 aPosition )
{
typedef typename basic_nsAReadableString<CharT> readable_t;
PRUint32 oldLength = Length();
SetLength(oldLength + aReadable.Length());
if ( aPosition < oldLength )
std::copy_backward(Begin(aPosition), Begin(oldLength), End());
copy_backward_chunky<CharT>(readable_t::Begin(aPosition), readable_t::Begin(oldLength), End());
else
aPosition = oldLength;
std::copy(aReadable.Begin(), aReadable.End(), Begin(aPosition));
copy_chunky<CharT>(aReadable.Begin(), aReadable.End(), Begin(aPosition));
}
template <class CharT>
void
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
{
std::copy(Begin(cutStart+cutLength), End(), Begin(cutStart));
typedef typename basic_nsAReadableString<CharT> readable_t;
copy_chunky<CharT>(readable_t::Begin(cutStart+cutLength), readable_t::End(), Begin(cutStart));
SetLength(Length()-cutLength);
}
@ -339,13 +450,15 @@ basic_nsAWritableString<CharT>::Replace( PRUint32 cutStart, PRUint32 cutLength,
PRUint32 newLength = oldLength - cutLength + replacementLength;
typedef typename basic_nsAReadableString<CharT> readable_t;
if ( cutLength > replacementLength )
std::copy(Begin(cutEnd), End(), Begin(replacementEnd));
copy_chunky<CharT>(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<CharT>(readable_t::Begin(cutEnd), readable_t::Begin(oldLength), Begin(replacementEnd));
std::copy(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
copy_chunky<CharT>(aReplacement.Begin(), aReplacement.End(), Begin(cutStart));
}
// operator>>