gecko-dev/string/public/nsAString.h

863 строки
31 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Netscape
* Communications. Portions created by Netscape Communications are
* Copyright (C) 2001 by Netscape Communications. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsAString_h___
#define nsAString_h___
#ifndef nsStringFwd_h___
#include "nsStringFwd.h"
#endif
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
#endif
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
#endif
#ifndef nsStringIterator_h___
#include "nsStringIterator.h"
#endif
/**
*
*/
class NS_COM nsAString
{
public:
typedef PRUnichar char_type;
typedef char incompatible_char_type;
typedef nsBufferHandle<char_type> buffer_handle_type;
typedef nsConstBufferHandle<char_type> const_buffer_handle_type;
typedef nsSharedBufferHandle<char_type> shared_buffer_handle_type;
typedef nsReadableFragment<char_type> const_fragment_type;
typedef nsWritableFragment<char_type> fragment_type;
typedef nsAString self_type;
typedef nsAString abstract_string_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef nsAPromiseString promise_type;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
public:
// nsAString(); // auto-generated default constructor OK (we're abstract anyway)
// nsAString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsAString() { } // ...yes, I expect to be sub-classed
virtual PRUint32 GetImplementationFlags() const;
virtual const buffer_handle_type* GetFlatBufferHandle() const;
virtual const buffer_handle_type* GetBufferHandle() const;
virtual const shared_buffer_handle_type* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
virtual PRBool IsVoid() const;
virtual void SetIsVoid( PRBool );
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, index_type aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( const_fragment_type&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( fragment_type&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool IsDependentOn( const self_type& aString ) const { return &aString == this; }
};
class NS_COM nsACString
{
public:
typedef char char_type;
typedef PRUnichar incompatible_char_type;
typedef nsBufferHandle<char_type> buffer_handle_type;
typedef nsConstBufferHandle<char_type> const_buffer_handle_type;
typedef nsSharedBufferHandle<char_type> shared_buffer_handle_type;
typedef nsReadableFragment<char_type> const_fragment_type;
typedef nsWritableFragment<char_type> fragment_type;
typedef nsACString self_type;
typedef nsACString abstract_string_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef nsAPromiseCString promise_type;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
// nsACString(); // auto-generated default constructor OK (we're abstract anyway)
// nsACString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsACString() { } // ...yes, I expect to be sub-classed
virtual PRUint32 GetImplementationFlags() const;
virtual const buffer_handle_type* GetFlatBufferHandle() const;
virtual const buffer_handle_type* GetBufferHandle() const;
virtual const shared_buffer_handle_type* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
virtual PRBool IsVoid() const;
virtual void SetIsVoid( PRBool );
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, PRUint32 aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( const_fragment_type&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( fragment_type&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool IsDependentOn( const self_type& aString ) const { return &aString == this; }
};
#include "nsAPromiseString.h"
inline
void
nsAString::Assign( const nsAPromiseString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsAString::Append( const nsAPromiseString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsAString::Insert( const nsAPromiseString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
inline
void
nsACString::Assign( const nsAPromiseCString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsACString::Append( const nsAPromiseCString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsACString::Insert( const nsAPromiseCString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
/**
* Note: measure -- should the |Begin...| and |End...| be |inline|?
*/
inline
nsAString::const_iterator&
nsAString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::const_iterator&
nsAString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsAString::iterator&
nsAString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::iterator&
nsAString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
class NS_COM nsStringComparator
{
public:
typedef nsAString::char_type char_type;
virtual int operator()( const char_type*, const char_type*, PRUint32 aLength ) const = 0;
virtual int operator()( char_type, char_type ) const = 0;
};
class NS_COM nsDefaultStringComparator
: public nsStringComparator
{
public:
virtual int operator()( const char_type*, const char_type*, PRUint32 aLength ) const;
virtual int operator() ( char_type, char_type ) const;
};
NS_COM int Compare( const nsAString& lhs, const nsAString& rhs, const nsStringComparator& = nsDefaultStringComparator() );
inline
PRBool
nsAString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsAString& lhs, const nsAString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsAString& lhs, const nsAString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsAString::size_type
nsAString::Left( nsAString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
/**
*
*/
inline
nsACString::const_iterator&
nsACString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::const_iterator&
nsACString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsACString::iterator&
nsACString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::iterator&
nsACString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
class NS_COM nsCStringComparator
{
public:
typedef nsACString::char_type char_type;
virtual int operator()( const char_type*, const char_type*, PRUint32 aLength ) const = 0;
virtual int operator() ( char_type, char_type ) const = 0;
};
class NS_COM nsDefaultCStringComparator
: public nsCStringComparator
{
public:
virtual int operator()( const char_type*, const char_type*, PRUint32 aLength ) const;
virtual int operator()( char_type, char_type ) const;
};
class NS_COM nsCaseInsensitiveCStringComparator
: public nsCStringComparator
{
public:
virtual int operator()( const char_type*, const char_type*, PRUint32 aLength ) const;
virtual int operator()( char_type, char_type ) const;
};
NS_COM int Compare( const nsACString& lhs, const nsACString& rhs, const nsCStringComparator& = nsDefaultCStringComparator() );
inline
PRBool
nsACString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsACString& lhs, const nsACString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsACString& lhs, const nsACString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsACString::size_type
nsACString::Left( nsACString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
// Once you've got strings, you shouldn't need to do anything else to have concatenation
#ifndef nsDependentConcatenation_h___
#include "nsDependentConcatenation.h"
#endif
#endif // !defined(nsAString_h___)