зеркало из https://github.com/mozilla/pjs.git
Made critical operations exploit chunky iterators. These files are not yet part of the build.
This commit is contained in:
Родитель
08dd4f1cdc
Коммит
09052fa5c9
|
@ -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,10 +265,12 @@ class basic_nsAWritableString
|
|||
virtual void SetLength( PRUint32 ) = 0;
|
||||
|
||||
|
||||
// ...a synonym for |SetLength()|
|
||||
void
|
||||
Truncate( PRUint32 aNewLength=0 )
|
||||
{
|
||||
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,10 +265,12 @@ class basic_nsAWritableString
|
|||
virtual void SetLength( PRUint32 ) = 0;
|
||||
|
||||
|
||||
// ...a synonym for |SetLength()|
|
||||
void
|
||||
Truncate( PRUint32 aNewLength=0 )
|
||||
{
|
||||
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,10 +265,12 @@ class basic_nsAWritableString
|
|||
virtual void SetLength( PRUint32 ) = 0;
|
||||
|
||||
|
||||
// ...a synonym for |SetLength()|
|
||||
void
|
||||
Truncate( PRUint32 aNewLength=0 )
|
||||
{
|
||||
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>>
|
||||
|
|
Загрузка…
Ссылка в новой задаче