landing string branch; see bug #73786

git-svn-id: svn://10.0.0.236/trunk@91049 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
scc%mozilla.org
2001-04-02 19:40:52 +00:00
parent e12df9c36a
commit 7b06841b03
143 changed files with 11372 additions and 5238 deletions

View File

@@ -18,6 +18,7 @@
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
@@ -33,8 +34,16 @@ LIBRARY_NAME = string_s
REQUIRES = xpcom
CPPSRCS = \
nsAFlatString.cpp \
nsAString.cpp \
nsCommonString.cpp \
nsFragmentedString.cpp \
nsLocalString.cpp \
nsPrintfCString.cpp \
nsPrivateSharableString.cpp \
nsPromiseConcatenation.cpp \
nsPromiseFlatString.cpp \
nsPromiseSubstring.cpp \
nsReadableUtils.cpp \
nsSharedBufferList.cpp \
nsSlidingString.cpp \

View File

@@ -19,6 +19,7 @@
#
# Contributor(s):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
@@ -28,8 +29,16 @@ LIBRARY_NAME=string_s
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
CPP_OBJS = \
.\$(OBJDIR)\nsAFlatString.obj \
.\$(OBJDIR)\nsAString.obj \
.\$(OBJDIR)\nsCommonString.obj \
.\$(OBJDIR)\nsFragmentedString.obj \
.\$(OBJDIR)\nsLocalString.obj \
.\$(OBJDIR)\nsPrintfCString.obj \
.\$(OBJDIR)\nsPrivateSharableString.obj \
.\$(OBJDIR)\nsPromiseConcatenation.obj \
.\$(OBJDIR)\nsPromiseFlatString.obj \
.\$(OBJDIR)\nsPromiseSubstring.obj \
.\$(OBJDIR)\nsReadableUtils.obj \
.\$(OBJDIR)\nsSharedBufferList.obj \
.\$(OBJDIR)\nsSlidingString.obj \

View File

@@ -0,0 +1,116 @@
/* -*- 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)
*/
#include "nsAFlatString.h"
const PRUnichar*
nsAFlatString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
const nsBufferHandle<PRUnichar>* buffer = GetBufferHandle();
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
PRUnichar*
nsAFlatString::GetWritableFragment( nsWritableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
nsBufferHandle<PRUnichar>* buffer = NS_CONST_CAST(nsBufferHandle<PRUnichar>*, GetBufferHandle());
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
const char*
nsAFlatCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
const nsBufferHandle<char>* buffer = GetBufferHandle();
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
char*
nsAFlatCString::GetWritableFragment( nsWritableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
{
nsBufferHandle<char>* buffer = NS_CONST_CAST(nsBufferHandle<char>*, GetBufferHandle());
NS_ASSERTION(buffer, "trouble: no buffer!");
aFragment.mEnd = buffer->DataEnd();
return (aFragment.mStart = buffer->DataStart()) + aOffset;
}
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}

View File

@@ -0,0 +1,921 @@
/* -*- 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)
*/
#include "nsAString.h"
#include "nsPromiseSubstring.h"
#include "nsLocalString.h"
NS_COM
int
Compare( const nsAString& lhs, const nsAString& rhs )
{
typedef nsAString::size_type size_type;
if ( &lhs == &rhs )
return 0;
size_type lLength = lhs.Length();
size_type rLength = rhs.Length();
size_type lengthToCompare = NS_MIN(lLength, rLength);
nsAString::const_iterator leftIter, rightIter;
lhs.BeginReading(leftIter);
rhs.BeginReading(rightIter);
int result;
for (;;)
{
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
if ( lengthAvailable > lengthToCompare )
lengthAvailable = lengthToCompare;
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
if ( (result = nsCharTraits<PRUnichar>::compare(leftIter.get(), rightIter.get(), lengthAvailable)) != 0 )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter.advance( PRInt32(lengthAvailable) );
rightIter.advance( PRInt32(lengthAvailable) );
}
if ( lLength < rLength )
return -1;
else if ( rLength < lLength )
return 1;
else
return 0;
}
PRBool
nsAString::Equals( const char_type* rhs ) const
{
return Equals(nsLocalString(rhs));
}
nsAString::char_type
nsAString::First() const
{
NS_ASSERTION(Length()>0, "|First()| on an empty string");
const_iterator iter;
return *BeginReading(iter);
}
nsAString::char_type
nsAString::Last() const
{
NS_ASSERTION(Length()>0, "|Last()| on an empty string");
const_iterator iter;
if ( !IsEmpty() )
{
EndReading(iter);
iter.advance(-1);
}
return *iter; // Note: this has undefined results if |IsEmpty()|
}
nsAString::size_type
nsAString::CountChar( char_type c ) const
{
/*
re-write this to use a counting sink
*/
size_type result = 0;
size_type lengthToExamine = Length();
const_iterator iter;
for ( BeginReading(iter); ; )
{
PRInt32 lengthToExamineInThisFragment = iter.size_forward();
const char_type* fromBegin = iter.get();
result += size_type(NS_COUNT(fromBegin, fromBegin+lengthToExamineInThisFragment, c));
if ( !(lengthToExamine -= lengthToExamineInThisFragment) )
return result;
iter.advance(lengthToExamineInThisFragment);
}
// never reached; quiets warnings
return 0;
}
nsAString::size_type
nsAString::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
{
// If we're just assigning our entire self, give |aResult| the opportunity to share
if ( aStartPos == 0 && aLengthToCopy >= Length() )
aResult = *this;
else
aResult = Substring(*this, aStartPos, aLengthToCopy);
return aResult.Length();
}
nsAString::size_type
nsAString::Right( self_type& aResult, size_type aLengthToCopy ) const
{
size_type myLength = Length();
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
}
PRInt32
nsAString::FindChar( char_type aChar, PRUint32 aOffset ) const
{
const_iterator iter, done_searching;
BeginReading(iter).advance( PRInt32(aOffset) );
EndReading(done_searching);
size_type lengthSearched = 0;
while ( iter != done_searching )
{
PRInt32 fragmentLength = iter.size_forward();
const char_type* charFoundAt = nsCharTraits<char_type>::find(iter.get(), fragmentLength, aChar);
if ( charFoundAt )
return lengthSearched + (charFoundAt-iter.get()) + aOffset;
lengthSearched += fragmentLength;
iter.advance(fragmentLength);
}
return -1;
}
//
// |Assign()|
//
void
nsAString::AssignFromReadable( const self_type& rhs )
{
if ( this != &rhs )
do_AssignFromReadable(rhs);
// else, self-assign is a no-op
}
void
nsAString::AssignFromPromise( const self_type& aReadable )
/*
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
E.g.,
... writable& w ...
... readable& r ...
w = r + w;
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
of |r| before being retrieved to be appended.
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
in the case above, |Insert| could have special behavior with significantly better performance. Since
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
entire promise. If we measure and this turns out to show up on performance radar, we then have the
option to fix either the callers or this mechanism.
*/
{
if ( !aReadable.Promises(*this) )
do_AssignFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
// Note: not exception safe. We need something to manage temporary buffers like this
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AssignFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsAString::do_AssignFromReadable( const self_type& aReadable )
{
SetLength(0);
SetLength(aReadable.Length());
// first setting the length to |0| avoids copying characters only to be overwritten later
// in the case where the implementation decides to re-allocate
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
}
void
nsAString::do_AssignFromElementPtr( const char_type* aPtr )
{
do_AssignFromReadable(nsLocalString(aPtr));
}
void
nsAString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsLocalString(aPtr, aLength));
}
void
nsAString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsLocalString(&aChar, 1));
}
//
// |Append()|
//
void
nsAString::AppendFromReadable( const self_type& aReadable )
{
if ( this != &aReadable )
do_AppendFromReadable(aReadable);
else
AppendFromPromise(aReadable);
}
void
nsAString::AppendFromPromise( const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_AppendFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AppendFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsAString::do_AppendFromReadable( const self_type& aReadable )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
}
void
nsAString::do_AppendFromElementPtr( const char_type* aChar )
{
do_AppendFromReadable(nsLocalString(aChar));
}
void
nsAString::do_AppendFromElementPtrLength( const char_type* aChar, size_type aLength )
{
do_AppendFromReadable(nsLocalString(aChar, aLength));
}
void
nsAString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsLocalString(&aChar, 1));
}
//
// |Insert()|
//
void
nsAString::InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
if ( this != &aReadable )
do_InsertFromReadable(aReadable, atPosition);
else
InsertFromPromise(aReadable, atPosition);
}
void
nsAString::InsertFromPromise( const self_type& aReadable, index_type atPosition )
{
if ( !aReadable.Promises(*this) )
do_InsertFromReadable(aReadable, atPosition);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_InsertFromElementPtrLength(buffer, atPosition, length);
delete buffer;
}
// else assert
}
}
void
nsAString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( atPosition < oldLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
else
atPosition = oldLength;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
}
void
nsAString::do_InsertFromElementPtr( const char_type* aPtr, index_type atPosition )
{
do_InsertFromReadable(nsLocalString(aPtr), atPosition);
}
void
nsAString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsLocalString(aPtr, aLength), atPosition);
}
void
nsAString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsLocalString(&aChar, 1), atPosition);
}
//
// |Cut()|
//
void
nsAString::Cut( index_type cutStart, size_type cutLength )
{
size_type myLength = this->Length();
cutLength = NS_MIN(cutLength, myLength-cutStart);
index_type cutEnd = cutStart + cutLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutEnd < myLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
SetLength(myLength-cutLength);
}
//
// |Replace()|
//
void
nsAString::ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
if ( this != &aReplacement )
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
else
ReplaceFromPromise(cutStart, cutLength, aReplacement);
}
void
nsAString::ReplaceFromPromise( index_type cutStart, size_type cutLength, const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_ReplaceFromReadable(cutStart, cutLength, nsLocalString(buffer, length));
delete buffer;
}
// else assert?
}
}
void
nsAString::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
size_type oldLength = this->Length();
cutStart = NS_MIN(cutStart, oldLength);
cutLength = NS_MIN(cutLength, oldLength-cutStart);
index_type cutEnd = cutStart + cutLength;
size_type replacementLength = aReplacement.Length();
index_type replacementEnd = cutStart + replacementLength;
size_type newLength = oldLength - cutLength + replacementLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutLength > replacementLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
SetLength(newLength);
if ( cutLength < replacementLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
}
NS_COM
int
Compare( const nsACString& lhs, const nsACString& rhs )
{
typedef nsACString::size_type size_type;
if ( &lhs == &rhs )
return 0;
size_type lLength = lhs.Length();
size_type rLength = rhs.Length();
size_type lengthToCompare = NS_MIN(lLength, rLength);
nsACString::const_iterator leftIter, rightIter;
lhs.BeginReading(leftIter);
rhs.BeginReading(rightIter);
int result;
for (;;)
{
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
if ( lengthAvailable > lengthToCompare )
lengthAvailable = lengthToCompare;
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
if ( (result = nsCharTraits<char>::compare(leftIter.get(), rightIter.get(), lengthAvailable)) != 0 )
return result;
if ( !(lengthToCompare -= lengthAvailable) )
break;
leftIter.advance( PRInt32(lengthAvailable) );
rightIter.advance( PRInt32(lengthAvailable) );
}
if ( lLength < rLength )
return -1;
else if ( rLength < lLength )
return 1;
else
return 0;
}
PRBool
nsACString::Equals( const char_type* rhs ) const
{
return Equals(nsLocalCString(rhs));
}
nsACString::char_type
nsACString::First() const
{
NS_ASSERTION(Length()>0, "|First()| on an empty string");
const_iterator iter;
return *BeginReading(iter);
}
nsACString::char_type
nsACString::Last() const
{
NS_ASSERTION(Length()>0, "|Last()| on an empty string");
const_iterator iter;
if ( !IsEmpty() )
{
EndReading(iter);
iter.advance(-1);
}
return *iter; // Note: this has undefined results if |IsEmpty()|
}
nsACString::size_type
nsACString::CountChar( char_type c ) const
{
/*
re-write this to use a counting sink
*/
size_type result = 0;
size_type lengthToExamine = Length();
const_iterator iter;
for ( BeginReading(iter); ; )
{
PRInt32 lengthToExamineInThisFragment = iter.size_forward();
const char_type* fromBegin = iter.get();
result += size_type(NS_COUNT(fromBegin, fromBegin+lengthToExamineInThisFragment, c));
if ( !(lengthToExamine -= lengthToExamineInThisFragment) )
return result;
iter.advance(lengthToExamineInThisFragment);
}
// never reached; quiets warnings
return 0;
}
nsACString::size_type
nsACString::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
{
// If we're just assigning our entire self, give |aResult| the opportunity to share
if ( aStartPos == 0 && aLengthToCopy >= Length() )
aResult = *this;
else
aResult = Substring(*this, aStartPos, aLengthToCopy);
return aResult.Length();
}
nsACString::size_type
nsACString::Right( self_type& aResult, size_type aLengthToCopy ) const
{
size_type myLength = Length();
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
}
PRInt32
nsACString::FindChar( char_type aChar, PRUint32 aOffset ) const
{
const_iterator iter, done_searching;
BeginReading(iter).advance( PRInt32(aOffset) );
EndReading(done_searching);
size_type lengthSearched = 0;
while ( iter != done_searching )
{
PRInt32 fragmentLength = iter.size_forward();
const char_type* charFoundAt = nsCharTraits<char_type>::find(iter.get(), fragmentLength, aChar);
if ( charFoundAt )
return lengthSearched + (charFoundAt-iter.get()) + aOffset;
lengthSearched += fragmentLength;
iter.advance(fragmentLength);
}
return -1;
}
//
// |Assign()|
//
void
nsACString::AssignFromReadable( const self_type& rhs )
{
if ( this != &rhs )
do_AssignFromReadable(rhs);
// else, self-assign is a no-op
}
void
nsACString::AssignFromPromise( const self_type& aReadable )
/*
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
E.g.,
... writable& w ...
... readable& r ...
w = r + w;
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
of |r| before being retrieved to be appended.
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
in the case above, |Insert| could have special behavior with significantly better performance. Since
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
entire promise. If we measure and this turns out to show up on performance radar, we then have the
option to fix either the callers or this mechanism.
*/
{
if ( !aReadable.Promises(*this) )
do_AssignFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
// Note: not exception safe. We need something to manage temporary buffers like this
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AssignFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsACString::do_AssignFromReadable( const self_type& aReadable )
{
SetLength(0);
SetLength(aReadable.Length());
// first setting the length to |0| avoids copying characters only to be overwritten later
// in the case where the implementation decides to re-allocate
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
}
void
nsACString::do_AssignFromElementPtr( const char_type* aPtr )
{
do_AssignFromReadable(nsLocalCString(aPtr));
}
void
nsACString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsLocalCString(aPtr, aLength));
}
void
nsACString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsLocalCString(&aChar, 1));
}
//
// |Append()|
//
void
nsACString::AppendFromReadable( const self_type& aReadable )
{
if ( this != &aReadable )
do_AppendFromReadable(aReadable);
else
AppendFromPromise(aReadable);
}
void
nsACString::AppendFromPromise( const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_AppendFromReadable(aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_AppendFromElementPtrLength(buffer, length);
delete buffer;
}
// else assert?
}
}
void
nsACString::do_AppendFromReadable( const self_type& aReadable )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
}
void
nsACString::do_AppendFromElementPtr( const char_type* aChar )
{
do_AppendFromReadable(nsLocalCString(aChar));
}
void
nsACString::do_AppendFromElementPtrLength( const char_type* aChar, size_type aLength )
{
do_AppendFromReadable(nsLocalCString(aChar, aLength));
}
void
nsACString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsLocalCString(&aChar, 1));
}
//
// |Insert()|
//
void
nsACString::InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
if ( this != &aReadable )
do_InsertFromReadable(aReadable, atPosition);
else
InsertFromPromise(aReadable, atPosition);
}
void
nsACString::InsertFromPromise( const self_type& aReadable, index_type atPosition )
{
if ( !aReadable.Promises(*this) )
do_InsertFromReadable(aReadable, atPosition);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_InsertFromElementPtrLength(buffer, atPosition, length);
delete buffer;
}
// else assert
}
}
void
nsACString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
{
size_type oldLength = this->Length();
SetLength(oldLength + aReadable.Length());
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( atPosition < oldLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(atPosition)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), EndWriting(toBegin));
else
atPosition = oldLength;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(atPosition)));
}
void
nsACString::do_InsertFromElementPtr( const char_type* aPtr, index_type atPosition )
{
do_InsertFromReadable(nsLocalCString(aPtr), atPosition);
}
void
nsACString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsLocalCString(aPtr, aLength), atPosition);
}
void
nsACString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsLocalCString(&aChar, 1), atPosition);
}
//
// |Cut()|
//
void
nsACString::Cut( index_type cutStart, size_type cutLength )
{
size_type myLength = this->Length();
cutLength = NS_MIN(cutLength, myLength-cutStart);
index_type cutEnd = cutStart + cutLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutEnd < myLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
SetLength(myLength-cutLength);
}
//
// |Replace()|
//
void
nsACString::ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
if ( this != &aReplacement )
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
else
ReplaceFromPromise(cutStart, cutLength, aReplacement);
}
void
nsACString::ReplaceFromPromise( index_type cutStart, size_type cutLength, const self_type& aReadable )
{
if ( !aReadable.Promises(*this) )
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
else
{
size_type length = aReadable.Length();
char_type* buffer = new char_type[length];
if ( buffer )
{
const_iterator fromBegin, fromEnd;
char_type* toBegin = buffer;
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
do_ReplaceFromReadable(cutStart, cutLength, nsLocalCString(buffer, length));
delete buffer;
}
// else assert?
}
}
void
nsACString::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReplacement )
{
size_type oldLength = this->Length();
cutStart = NS_MIN(cutStart, oldLength);
cutLength = NS_MIN(cutLength, oldLength-cutStart);
index_type cutEnd = cutStart + cutLength;
size_type replacementLength = aReplacement.Length();
index_type replacementEnd = cutStart + replacementLength;
size_type newLength = oldLength - cutLength + replacementLength;
const_iterator fromBegin, fromEnd;
iterator toBegin;
if ( cutLength > replacementLength )
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
SetLength(newLength);
if ( cutLength < replacementLength )
copy_string_backward(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->BeginReading(fromEnd).advance(PRInt32(oldLength)), BeginWriting(toBegin).advance(PRInt32(replacementEnd)));
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
}

View File

@@ -0,0 +1,58 @@
/* -*- 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)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsCommonString.h"
// #include "nsBufferHandleUtils.h"
void
nsCommonString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<PRUnichar>*
nsCommonString::GetSharedBufferHandle() const
{
return mBuffer.get();
}
void
nsCommonCString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<char>*
nsCommonCString::GetSharedBufferHandle() const
{
return mBuffer.get();
}

View File

@@ -0,0 +1,197 @@
/* -*- 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)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsAString.h"
// remember, no one should include "nsPromiseConcatenation.h" themselves
// one always gets it through "nsAString.h"
PRUint32
nsPromiseConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const PRUnichar*
nsPromiseConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}
PRUint32
nsPromiseCConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseCConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseCConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const char*
nsPromiseCConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}

View File

@@ -0,0 +1,25 @@
/* -*- 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)
*/
#include "nsLocalString.h"

View File

@@ -0,0 +1,123 @@
/* -*- 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)
*/
#include "nsPromiseSubstring.h"
PRUint32
nsPromiseSubstring::Length() const
{
return mLength;
}
const PRUnichar*
nsPromiseSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const PRUnichar* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}
PRUint32
nsPromiseCSubstring::Length() const
{
return mLength;
}
const char*
nsPromiseCSubstring::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const char* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}

View File

@@ -0,0 +1,25 @@
/* -*- 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)
*/
#include "nsLocalString.h"

View File

@@ -0,0 +1,85 @@
/* -*- 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)
*/
#include "nsPrivateSharableString.h"
//-------1---------2---------3---------4---------5---------6---------7---------8
const nsSharedBufferHandle<PRUnichar>*
nsPrivateSharableString::GetSharedBufferHandle() const
{
return 0;
}
const nsBufferHandle<PRUnichar>*
nsPrivateSharableString::GetFlatBufferHandle() const
{
return GetSharedBufferHandle();
}
const nsBufferHandle<PRUnichar>*
nsPrivateSharableString::GetBufferHandle() const
{
return GetSharedBufferHandle();
}
PRUint32
nsPrivateSharableString::GetImplementationFlags() const
{
PRUint32 flags = 0;
const nsSharedBufferHandle<char_type>* handle = GetSharedBufferHandle();
if ( handle )
flags = handle->GetImplementationFlags();
return flags;
}
const nsSharedBufferHandle<char>*
nsPrivateSharableCString::GetSharedBufferHandle() const
{
return 0;
}
const nsBufferHandle<char>*
nsPrivateSharableCString::GetFlatBufferHandle() const
{
return GetSharedBufferHandle();
}
const nsBufferHandle<char>*
nsPrivateSharableCString::GetBufferHandle() const
{
return GetSharedBufferHandle();
}
PRUint32
nsPrivateSharableCString::GetImplementationFlags() const
{
PRUint32 flags = 0;
const nsSharedBufferHandle<char_type>* handle = GetSharedBufferHandle();
if ( handle )
flags = handle->GetImplementationFlags();
return flags;
}

View File

@@ -0,0 +1,197 @@
/* -*- 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)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsAString.h"
// remember, no one should include "nsPromiseConcatenation.h" themselves
// one always gets it through "nsAString.h"
PRUint32
nsPromiseConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const PRUnichar*
nsPromiseConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}
PRUint32
nsPromiseCConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsPromiseCConcatenation::Promises( const string_type& aString ) const
{
return mStrings[0]->Promises(aString) || mStrings[1]->Promises(aString);
}
#if 0
PRBool
nsPromiseCConcatenation::PromisesExactly( const string_type& aString ) const
{
// Not really like this, test for the empty string, etc
return mStrings[0] == &aString && !mStrings[1] || !mStrings[0] && mStrings[1] == &aString;
}
#endif
const char*
nsPromiseCConcatenation::GetReadableFragment( nsReadableFragment<char_type>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
int whichString;
// based on the request, pick which string we will forward the |GetReadableFragment()| call into
switch ( aRequest )
{
case kPrevFragment:
case kNextFragment:
whichString = GetCurrentStringFromFragment(aFragment);
break;
case kFirstFragment:
whichString = SetLeftStringInFragment(aFragment);
break;
case kLastFragment:
whichString = SetRightStringInFragment(aFragment);
break;
case kFragmentAt:
PRUint32 leftLength = mStrings[kLeftString]->Length();
if ( aPosition < leftLength )
whichString = SetLeftStringInFragment(aFragment);
else
{
whichString = SetRightStringInFragment(aFragment);
aPosition -= leftLength;
}
break;
}
const char_type* result;
PRBool done;
do
{
done = PR_TRUE;
result = mStrings[whichString]->GetReadableFragment(aFragment, aRequest, aPosition);
if ( !result )
{
done = PR_FALSE;
if ( aRequest == kNextFragment && whichString == kLeftString )
{
aRequest = kFirstFragment;
whichString = SetRightStringInFragment(aFragment);
}
else if ( aRequest == kPrevFragment && whichString == kRightString )
{
aRequest = kLastFragment;
whichString = SetLeftStringInFragment(aFragment);
}
else
done = PR_TRUE;
}
}
while ( !done );
return result;
}

View File

@@ -0,0 +1,116 @@
/* -*- 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)
*/
#include "nsPromiseFlatString.h"
nsPromiseFlatString::nsPromiseFlatString( const nsPromiseFlatString& aOther )
: mFlattenedString(aOther.mFlattenedString)
{
if ( aOther.mPromisedString == &aOther.mFlattenedString )
mPromisedString = &mFlattenedString;
else
mPromisedString = aOther.mPromisedString;
}
nsPromiseFlatString::nsPromiseFlatString( const nsAString& aString )
{
if ( aString.GetFlatBufferHandle() )
mPromisedString = NS_STATIC_CAST(const nsAFlatString*, &aString);
else
{
mFlattenedString = aString; // flatten |aString|
mPromisedString = &mFlattenedString;
}
}
const PRUnichar*
nsPromiseFlatString::get() const
{
return mPromisedString->get();
}
const nsBufferHandle<PRUnichar>*
nsPromiseFlatString::GetFlatBufferHandle() const
{
return mPromisedString->GetFlatBufferHandle();
}
const nsBufferHandle<PRUnichar>*
nsPromiseFlatString::GetBufferHandle() const
{
return mPromisedString->GetBufferHandle();
}
const nsSharedBufferHandle<PRUnichar>*
nsPromiseFlatString::GetSharedBufferHandle() const
{
return mPromisedString->GetSharedBufferHandle();
}
nsPromiseFlatCString::nsPromiseFlatCString( const nsPromiseFlatCString& aOther )
: mFlattenedString(aOther.mFlattenedString)
{
if ( aOther.mPromisedString == &aOther.mFlattenedString )
mPromisedString = &mFlattenedString;
else
mPromisedString = aOther.mPromisedString;
}
nsPromiseFlatCString::nsPromiseFlatCString( const nsACString& aString )
{
if ( aString.GetFlatBufferHandle() )
mPromisedString = NS_STATIC_CAST(const nsAFlatCString*, &aString);
else
{
mFlattenedString = aString; // flatten |aString|
mPromisedString = &mFlattenedString;
}
}
const char*
nsPromiseFlatCString::get() const
{
return mPromisedString->get();
}
const nsBufferHandle<char>*
nsPromiseFlatCString::GetFlatBufferHandle() const
{
return mPromisedString->GetFlatBufferHandle();
}
const nsBufferHandle<char>*
nsPromiseFlatCString::GetBufferHandle() const
{
return mPromisedString->GetBufferHandle();
}
const nsSharedBufferHandle<char>*
nsPromiseFlatCString::GetSharedBufferHandle() const
{
return mPromisedString->GetSharedBufferHandle();
}

View File

@@ -0,0 +1,123 @@
/* -*- 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)
*/
#include "nsPromiseSubstring.h"
PRUint32
nsPromiseSubstring::Length() const
{
return mLength;
}
const PRUnichar*
nsPromiseSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const PRUnichar* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}
PRUint32
nsPromiseCSubstring::Length() const
{
return mLength;
}
const char*
nsPromiseCSubstring::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aPosition ) const
{
// Offset any request for a specific position (First, Last, At) by our
// substrings startpos within the owning string
if ( aRequest == kFirstFragment )
{
aPosition = mStartPos;
aRequest = kFragmentAt;
}
else if ( aRequest == kLastFragment )
{
aPosition = mStartPos + mLength;
aRequest = kFragmentAt;
}
else if ( aRequest == kFragmentAt )
aPosition += mStartPos;
// requests for |kNextFragment| or |kPrevFragment| are just relayed down into the string we're slicing
const char* position_ptr = mString.GetReadableFragment(aFragment, aRequest, aPosition);
// If |GetReadableFragment| returns |0|, then we are off the string, the contents of the
// fragment are garbage.
// Therefore, only need to fix up the fragment boundaries when |position_ptr| is not null
if ( position_ptr )
{
// if there's more physical data in the returned fragment than I logically have left...
size_t logical_size_backward = aPosition - mStartPos;
if ( size_t(position_ptr - aFragment.mStart) > logical_size_backward )
aFragment.mStart = position_ptr - logical_size_backward;
size_t logical_size_forward = mLength - logical_size_backward;
if ( size_t(aFragment.mEnd - position_ptr) > logical_size_forward )
aFragment.mEnd = position_ptr + logical_size_forward;
}
return position_ptr;
}

View File

@@ -26,6 +26,9 @@
#include "nsString.h"
#include "nsCRT.h"
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
/**
* this allocator definition, and the global functions to access it need to move
@@ -142,7 +145,7 @@ class LossyConvertEncoding
NS_COM
void
CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest )
CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
@@ -157,7 +160,7 @@ CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest )
NS_COM
void
CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest )
CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
@@ -178,10 +181,10 @@ CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& aDest )
* @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
*
*/
template <class FromCharT, class ToCharT>
template <class FromStringT, class ToCharT>
inline
ToCharT*
AllocateStringCopy( const basic_nsAReadableString<FromCharT>& aSource, ToCharT* )
AllocateStringCopy( const FromStringT& aSource, ToCharT* )
{
return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
}
@@ -189,7 +192,7 @@ AllocateStringCopy( const basic_nsAReadableString<FromCharT>& aSource, ToCharT*
NS_COM
char*
ToNewCString( const nsAReadableString& aSource )
ToNewCString( const nsAString& aSource )
{
char* result = AllocateStringCopy(aSource, (char*)0);
@@ -201,7 +204,7 @@ ToNewCString( const nsAReadableString& aSource )
NS_COM
char*
ToNewUTF8String( const nsAReadableString& aSource )
ToNewUTF8String( const nsAString& aSource )
{
NS_ConvertUCS2toUTF8 temp(aSource);
@@ -225,7 +228,7 @@ ToNewUTF8String( const nsAReadableString& aSource )
NS_COM
char*
ToNewCString( const nsAReadableCString& aSource )
ToNewCString( const nsACString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
@@ -239,7 +242,7 @@ ToNewCString( const nsAReadableCString& aSource )
NS_COM
PRUnichar*
ToNewUnicode( const nsAReadableString& aSource )
ToNewUnicode( const nsAString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
@@ -253,7 +256,7 @@ ToNewUnicode( const nsAReadableString& aSource )
NS_COM
PRUnichar*
ToNewUnicode( const nsAReadableCString& aSource )
ToNewUnicode( const nsACString& aSource )
{
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
@@ -265,7 +268,7 @@ ToNewUnicode( const nsAReadableCString& aSource )
NS_COM
PRUnichar*
CopyUnicodeTo( const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength )
CopyUnicodeTo( const nsAString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength )
{
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = aDest;
@@ -277,7 +280,7 @@ NS_COM
void
CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAWritableString& aDest )
nsAString& aDest )
{
nsWritingIterator<PRUnichar> writer;
aDest.SetLength(Distance(aSrcStart, aSrcEnd));
@@ -291,7 +294,7 @@ NS_COM
void
AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAWritableString& aDest )
nsAString& aDest )
{
nsWritingIterator<PRUnichar> writer;
PRUint32 oldLength = aDest.Length();
@@ -304,7 +307,7 @@ AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
NS_COM
PRBool
IsASCII( const nsAReadableString& aString )
IsASCII( const nsAString& aString )
{
static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
@@ -354,18 +357,18 @@ class ConvertToUpperCase
NS_COM
void
ToUpperCase( nsAWritableString& aString )
ToUpperCase( nsAString& aString )
{
nsAWritableString::iterator fromBegin, fromEnd;
nsAString::iterator fromBegin, fromEnd;
ConvertToUpperCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToUpperCase( nsAWritableCString& aCString )
ToUpperCase( nsACString& aCString )
{
nsAWritableCString::iterator fromBegin, fromEnd;
nsACString::iterator fromBegin, fromEnd;
ConvertToUpperCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}
@@ -391,18 +394,18 @@ class ConvertToLowerCase
NS_COM
void
ToLowerCase( nsAWritableString& aString )
ToLowerCase( nsAString& aString )
{
nsAWritableString::iterator fromBegin, fromEnd;
nsAString::iterator fromBegin, fromEnd;
ConvertToLowerCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToLowerCase( nsAWritableCString& aCString )
ToLowerCase( nsACString& aCString )
{
nsAWritableCString::iterator fromBegin, fromEnd;
nsACString::iterator fromBegin, fromEnd;
ConvertToLowerCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}
@@ -411,7 +414,7 @@ ToLowerCase( nsAWritableCString& aCString )
template <class CharT>
inline // probably wishful thinking
PRBool
FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
FindInReadable_Impl( const typename nsStringTraits<CharT>::abstract_string_type& aPattern,
nsReadingIterator<CharT>& aSearchStart,
nsReadingIterator<CharT>& aSearchEnd )
{
@@ -479,14 +482,14 @@ FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
NS_COM
PRBool
FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
FindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
}
NS_COM
PRBool
FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
FindInReadable( const nsACString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
}
@@ -499,7 +502,7 @@ FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSe
template <class CharT>
inline // probably wishful thinking
PRBool
RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
RFindInReadable_Impl( const typename nsStringTraits<CharT>::abstract_string_type& aPattern,
nsReadingIterator<CharT>& aSearchStart,
nsReadingIterator<CharT>& aSearchEnd )
{
@@ -535,14 +538,14 @@ RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
NS_COM
PRBool
RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
RFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
{
return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
}
NS_COM
PRBool
RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
RFindInReadable( const nsACString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
{
return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
}
@@ -593,7 +596,7 @@ FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, const nsR
template <class CharT>
PRUint32
CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr,
CountCharInReadable_Impl( const typename nsStringTraits<CharT>::abstract_string_type& aStr,
CharT aChar )
{
PRUint32 count = 0;
@@ -614,7 +617,7 @@ CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr,
NS_COM
PRUint32
CountCharInReadable( const nsAReadableString& aStr,
CountCharInReadable( const nsAString& aStr,
PRUnichar aChar )
{
return CountCharInReadable_Impl(aStr, aChar);
@@ -622,7 +625,7 @@ CountCharInReadable( const nsAReadableString& aStr,
NS_COM
PRUint32
CountCharInReadable( const nsAReadableCString& aStr,
CountCharInReadable( const nsACString& aStr,
char aChar )
{
return CountCharInReadable_Impl(aStr, aChar);

View File

@@ -0,0 +1,58 @@
/* -*- 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)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsCommonString.h"
// #include "nsBufferHandleUtils.h"
void
nsCommonString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<PRUnichar>*
nsCommonString::GetSharedBufferHandle() const
{
return mBuffer.get();
}
void
nsCommonCString::assign( const string_type& aReadable )
{
const nsSharedBufferHandle<char_type>* handle = aReadable.GetSharedBufferHandle();
if ( !handle )
handle = NS_AllocateContiguousHandleWithData(handle, aReadable, 1);
mBuffer = handle;
}
const nsSharedBufferHandle<char>*
nsCommonCString::GetSharedBufferHandle() const
{
return mBuffer.get();
}

View File

@@ -99,7 +99,7 @@ nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList )
typedef const nsSharedBufferList::Buffer* Buffer_ptr;
static nsSharedBufferList::Buffer*
AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAReadableString& aDataSource )
AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAString& aDataSource )
{
typedef const PRUnichar* PRUnichar_ptr;
@@ -131,7 +131,7 @@ AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAReadableS
return result;
}
nsSlidingSubstring::nsSlidingSubstring( const nsAReadableString& aSourceString )
nsSlidingSubstring::nsSlidingSubstring( const nsAString& aSourceString )
: mBufferList(new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString)))
{
init_range_from_buffer_list();
@@ -189,7 +189,7 @@ nsSlidingSubstring::Rebind( const nsSlidingString& aString, const nsReadingItera
}
void
nsSlidingSubstring::Rebind( const nsAReadableString& aSourceString )
nsSlidingSubstring::Rebind( const nsAString& aSourceString )
{
release_ownership_of_buffer_list();
mBufferList = new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString));
@@ -291,7 +291,7 @@ nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PR
}
void
nsSlidingString::InsertReadable( const nsAReadableString& aReadable, const nsReadingIterator<PRUnichar>& aInsertPoint )
nsSlidingString::InsertReadable( const nsAString& aReadable, const nsReadingIterator<PRUnichar>& aInsertPoint )
/*
* Warning: this routine manipulates the shared buffer list in an unexpected way.
* The original design did not really allow for insertions, but this call promises