зеркало из https://github.com/mozilla/pjs.git
landing 172512. nsEmbedString for component developers and embeders. r=alec, sr=jag/darin, a=asa@mozilla.org
This commit is contained in:
Родитель
ac0efa78fc
Коммит
a167020474
|
@ -30,13 +30,17 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MODULE = string
|
||||
|
||||
SDK_HEADERS = \
|
||||
nsAString.h \
|
||||
nsBufferHandle.h \
|
||||
nsStringFragment.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsAFlatString.h \
|
||||
nsAlgorithm.h \
|
||||
nsASingleFragmentString.h \
|
||||
nsAString.h \
|
||||
nsAStringGenerator.h \
|
||||
nsBufferHandle.h \
|
||||
nsBufferHandleUtils.h \
|
||||
nsCharTraits.h \
|
||||
nsDependentConcatenation.h \
|
||||
|
@ -51,7 +55,6 @@ EXPORTS = \
|
|||
nsSharedBufferList.h \
|
||||
nsSlidingString.h \
|
||||
nsStringDefines.h \
|
||||
nsStringFragment.h \
|
||||
nsStringFwd.h \
|
||||
nsStringIterator.h \
|
||||
nsStringIteratorUtils.h \
|
||||
|
|
|
@ -1,997 +0,0 @@
|
|||
/* -*- 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 "nsDependentSubstring.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
|
||||
int
|
||||
nsDefaultStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
|
||||
{
|
||||
return nsCharTraits<char_type>::compare(lhs, rhs, aLength);
|
||||
}
|
||||
|
||||
int
|
||||
nsDefaultStringComparator::operator()( char_type lhs, char_type rhs) const
|
||||
{
|
||||
return lhs - rhs;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
int
|
||||
Compare( const nsAString& lhs, const nsAString& rhs, const nsStringComparator& aComparator )
|
||||
{
|
||||
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);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
|
||||
|
||||
if ( lengthAvailable > lengthToCompare )
|
||||
lengthAvailable = lengthToCompare;
|
||||
|
||||
{
|
||||
int result;
|
||||
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
|
||||
if ( (result = aComparator(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;
|
||||
}
|
||||
|
||||
const nsAString::shared_buffer_handle_type*
|
||||
nsAString::GetSharedBufferHandle() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const nsAString::buffer_handle_type*
|
||||
nsAString::GetFlatBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
const nsAString::buffer_handle_type*
|
||||
nsAString::GetBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsAString::GetImplementationFlags() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsAString::IsVoid() const
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::SetIsVoid( PRBool )
|
||||
{
|
||||
// |SetIsVoid| is ignored by default
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAString::Equals( const char_type* rhs, const nsStringComparator& aComparator ) const
|
||||
{
|
||||
return Equals(nsDependentString(rhs), aComparator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAString::IsDependentOn( const self_type& aString ) const
|
||||
{
|
||||
const_fragment_type f1;
|
||||
const char_type* s1 = GetReadableFragment(f1, kFirstFragment);
|
||||
while ( s1 )
|
||||
{
|
||||
const_fragment_type f2;
|
||||
const char_type* s2 = aString.GetReadableFragment(f2, kFirstFragment);
|
||||
while ( s2 )
|
||||
{
|
||||
// if it _isn't_ the case that
|
||||
// one fragment starts after the other ends,
|
||||
// or ends before the other starts,
|
||||
// then, they conflict:
|
||||
// !(f2.mStart>=f1.mEnd || f2.mEnd<=f1.mStart)
|
||||
//
|
||||
// Simplified, that gives us:
|
||||
if ( f2.mStart < f1.mEnd && f2.mEnd > f1.mStart )
|
||||
return PR_TRUE;
|
||||
|
||||
s2 = aString.GetReadableFragment(f2, kNextFragment);
|
||||
}
|
||||
s1 = GetReadableFragment(f1, kNextFragment);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// |Assign()|
|
||||
//
|
||||
|
||||
void
|
||||
nsAString::do_AssignFromReadable( const self_type& aReadable )
|
||||
/*
|
||||
...we need to check whether the string that's being assigned into |this| somehow references |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.
|
||||
*/
|
||||
{
|
||||
// self-assign is a no-op
|
||||
if ( this == &aReadable)
|
||||
return;
|
||||
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedAssignFromReadable(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);
|
||||
UncheckedAssignFromReadable(Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::UncheckedAssignFromReadable( const self_type& aReadable )
|
||||
{
|
||||
SetLength(0);
|
||||
if ( !aReadable.IsEmpty() )
|
||||
{
|
||||
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(nsDependentString(aPtr));
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
|
||||
{
|
||||
do_AssignFromReadable(Substring(aPtr, aPtr+aLength));
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_AssignFromElement( char_type aChar )
|
||||
{
|
||||
UncheckedAssignFromReadable(Substring(&aChar, &aChar+1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|
|
||||
//
|
||||
|
||||
void
|
||||
nsAString::do_AppendFromReadable( const self_type& aReadable )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedAppendFromReadable(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);
|
||||
UncheckedAppendFromReadable(Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::UncheckedAppendFromReadable( 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* aPtr )
|
||||
{
|
||||
do_AppendFromReadable(nsDependentString(aPtr));
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_AppendFromElementPtrLength( const char_type* aPtr, size_type aLength )
|
||||
{
|
||||
do_AppendFromReadable(Substring(aPtr, aPtr+aLength));
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_AppendFromElement( char_type aChar )
|
||||
{
|
||||
UncheckedAppendFromReadable(Substring(&aChar, &aChar + 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Insert()|
|
||||
//
|
||||
|
||||
void
|
||||
nsAString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedInsertFromReadable(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);
|
||||
UncheckedInsertFromReadable(Substring(buffer, buffer + length), atPosition);
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::UncheckedInsertFromReadable( 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(nsDependentString(aPtr), atPosition);
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
|
||||
{
|
||||
do_InsertFromReadable(Substring(aPtr, aPtr+aLength), atPosition);
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::do_InsertFromElement( char_type aChar, index_type atPosition )
|
||||
{
|
||||
UncheckedInsertFromReadable(Substring(&aChar, &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::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReadable )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedReplaceFromReadable(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);
|
||||
UncheckedReplaceFromReadable(cutStart, cutLength, Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAString::UncheckedReplaceFromReadable( 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)), EndWriting(toBegin));
|
||||
|
||||
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
nsDefaultCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
|
||||
{
|
||||
return nsCharTraits<char_type>::compare(lhs, rhs, aLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDefaultCStringComparator::operator()( char_type lhs, char_type rhs ) const
|
||||
{
|
||||
return lhs - rhs;
|
||||
}
|
||||
|
||||
int
|
||||
nsCaseInsensitiveCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
|
||||
{
|
||||
return nsCRT::strncasecmp(lhs, rhs, aLength);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCaseInsensitiveCStringComparator::operator()( char lhs, char rhs ) const
|
||||
{
|
||||
if (lhs == rhs) return 0;
|
||||
|
||||
lhs = tolower(lhs);
|
||||
rhs = tolower(rhs);
|
||||
|
||||
return lhs - rhs;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
int
|
||||
Compare( const nsACString& lhs, const nsACString& rhs, const nsCStringComparator& aComparator )
|
||||
{
|
||||
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);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_type lengthAvailable = size_type( NS_MIN(leftIter.size_forward(), rightIter.size_forward()) );
|
||||
|
||||
if ( lengthAvailable > lengthToCompare )
|
||||
lengthAvailable = lengthToCompare;
|
||||
|
||||
{
|
||||
int result;
|
||||
// Note: |result| should be declared in this |if| expression, but some compilers don't like that
|
||||
if ( (result = aComparator(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;
|
||||
}
|
||||
|
||||
const nsACString::shared_buffer_handle_type*
|
||||
nsACString::GetSharedBufferHandle() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const nsACString::buffer_handle_type*
|
||||
nsACString::GetFlatBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
const nsACString::buffer_handle_type*
|
||||
nsACString::GetBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsACString::GetImplementationFlags() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsACString::IsVoid() const
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::SetIsVoid( PRBool )
|
||||
{
|
||||
// |SetIsVoid| is ignored by default
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsACString::Equals( const char_type* rhs, const nsCStringComparator& aComparator ) const
|
||||
{
|
||||
return Equals(nsDependentCString(rhs), aComparator);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsACString::IsDependentOn( const self_type& aString ) const
|
||||
{
|
||||
const_fragment_type f1;
|
||||
const char_type* s1 = GetReadableFragment(f1, kFirstFragment);
|
||||
while ( s1 )
|
||||
{
|
||||
const_fragment_type f2;
|
||||
const char_type* s2 = aString.GetReadableFragment(f2, kFirstFragment);
|
||||
while ( s2 )
|
||||
{
|
||||
// if it _isn't_ the case that
|
||||
// one fragment starts after the other ends,
|
||||
// or ends before the other starts,
|
||||
// then, they conflict:
|
||||
// !(f2.mStart>=f1.mEnd || f2.mEnd<=f1.mStart)
|
||||
//
|
||||
// Simplified, that gives us:
|
||||
if ( f2.mStart < f1.mEnd && f2.mEnd > f1.mStart )
|
||||
return PR_TRUE;
|
||||
|
||||
s2 = aString.GetReadableFragment(f2, kNextFragment);
|
||||
}
|
||||
s1 = GetReadableFragment(f1, kNextFragment);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// |Assign()|
|
||||
//
|
||||
|
||||
void
|
||||
nsACString::do_AssignFromReadable( const self_type& aReadable )
|
||||
/*
|
||||
...we need to check whether the string that's being assigned into |this| somehow references |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.
|
||||
*/
|
||||
{
|
||||
// self-assign is a no-op
|
||||
if (this == &aReadable)
|
||||
return;
|
||||
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedAssignFromReadable(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);
|
||||
UncheckedAssignFromReadable(Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::UncheckedAssignFromReadable( const self_type& aReadable )
|
||||
{
|
||||
SetLength(0);
|
||||
if ( !aReadable.IsEmpty() )
|
||||
{
|
||||
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(nsDependentCString(aPtr));
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
|
||||
{
|
||||
do_AssignFromReadable(Substring(aPtr, aPtr+aLength));
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_AssignFromElement( char_type aChar )
|
||||
{
|
||||
UncheckedAssignFromReadable(Substring(&aChar, &aChar+1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|
|
||||
//
|
||||
|
||||
void
|
||||
nsACString::do_AppendFromReadable( const self_type& aReadable )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedAppendFromReadable(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);
|
||||
UncheckedAppendFromReadable(Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::UncheckedAppendFromReadable( 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* aPtr )
|
||||
{
|
||||
do_AppendFromReadable(nsDependentCString(aPtr));
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_AppendFromElementPtrLength( const char_type* aPtr, size_type aLength )
|
||||
{
|
||||
do_AppendFromReadable(Substring(aPtr, aPtr+aLength));
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_AppendFromElement( char_type aChar )
|
||||
{
|
||||
UncheckedAppendFromReadable(Substring(&aChar, &aChar + 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Insert()|
|
||||
//
|
||||
|
||||
void
|
||||
nsACString::do_InsertFromReadable( const self_type& aReadable, index_type atPosition )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedInsertFromReadable(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);
|
||||
UncheckedInsertFromReadable(Substring(buffer, buffer + length), atPosition);
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::UncheckedInsertFromReadable( 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(nsDependentCString(aPtr), atPosition);
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
|
||||
{
|
||||
do_InsertFromReadable(Substring(aPtr, aPtr+aLength), atPosition);
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::do_InsertFromElement( char_type aChar, index_type atPosition )
|
||||
{
|
||||
UncheckedInsertFromReadable(Substring(&aChar, &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::do_ReplaceFromReadable( index_type cutStart, size_type cutLength, const self_type& aReadable )
|
||||
{
|
||||
if ( !aReadable.IsDependentOn(*this) )
|
||||
UncheckedReplaceFromReadable(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);
|
||||
UncheckedReplaceFromReadable(cutStart, cutLength, Substring(buffer, buffer + length));
|
||||
delete[] buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsACString::UncheckedReplaceFromReadable( 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)), EndWriting(toBegin));
|
||||
|
||||
copy_string(aReplacement.BeginReading(fromBegin), aReplacement.EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
|
||||
}
|
||||
|
|
@ -49,6 +49,18 @@
|
|||
*/
|
||||
#define NS_DIRECTORY_SERVICE_CONTRACTID "@mozilla.org/file/directory_service;1"
|
||||
|
||||
/**
|
||||
* XPCOM File
|
||||
* The file abstraction provides ways to obtain and access files and
|
||||
* directories located on the local system.
|
||||
*
|
||||
* This contract supports the nsIFile interface and the nsILocalFile interface.
|
||||
* This contract may also support platform specific interfaces such as
|
||||
* nsILocalFileMac on platforms where additional interfaces are required.
|
||||
*
|
||||
*/
|
||||
#define NS_LOCAL_FILE_CONTRACTID "@mozilla.org/file/local;1"
|
||||
|
||||
/**
|
||||
* XPCOM Category Manager Contract ID
|
||||
* The contract supports the nsICategoryManager interface. The
|
||||
|
|
|
@ -351,7 +351,7 @@ static const nsModuleComponentInfo components[] = {
|
|||
COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
|
||||
|
||||
#undef COMPONENT_SUPPORTS
|
||||
|
||||
#define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
|
||||
COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
|
||||
#define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service"
|
||||
COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsIFile.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsEmbedString.h"
|
||||
#endif
|
||||
|
||||
nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
|
||||
|
@ -297,7 +298,7 @@ nsGenericModule::Initialize(nsIComponentManager *compMgr)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCAutoString path;
|
||||
nsEmbedCString path;
|
||||
xpcomDll->GetNativePath(path);
|
||||
rv = XPCOMGlueStartup(path.get());
|
||||
|
||||
|
|
|
@ -48,21 +48,34 @@ LIBRARY_NAME = xpcomglue
|
|||
REQUIRES = string \
|
||||
$(NULL)
|
||||
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../build \
|
||||
$(NULL)
|
||||
|
||||
STRING_LCSRCS = \
|
||||
nsAString.cpp \
|
||||
nsDependentSubstring.cpp \
|
||||
nsASingleFragmentString.cpp \
|
||||
$(NULL)
|
||||
|
||||
STRING_CSRCS := $(addprefix $(topsrcdir)/string/src/, $(STRING_LCSRCS))
|
||||
|
||||
CPPSRCS = \
|
||||
$(XPCOM_GLUE_SRC_LCSRCS) \
|
||||
nsXPCOMGlue.cpp \
|
||||
$(XPCOM_GLUE_SRC_LCSRCS) \
|
||||
$(STRING_LCSRCS) \
|
||||
nsXPCOMGlue.cpp \
|
||||
nsEmbedString.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsXPCOMGlue.h \
|
||||
$(NULL)
|
||||
|
||||
SDK_BINARY = \
|
||||
SDK_HEADERS = \
|
||||
nsEmbedString.h \
|
||||
$(NULL)
|
||||
|
||||
SDK_BINARY = \
|
||||
$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
|
@ -73,9 +86,11 @@ FORCE_STATIC_LIB = 1
|
|||
FORCE_USE_PIC = 1
|
||||
|
||||
GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(wildcard *.$(OBJ_SUFFIX))
|
||||
GARBAGE += $(STRING_LCSRCS) $(wildcard *.$(OBJ_SUFFIX))
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
GARBAGE += $(addprefix $(srcdir)/,$(XPCOM_GLUE_SRC_LCSRCS))
|
||||
GARBAGE += $(addprefix $(srcdir)/,$(STRING_LCSRCS))
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -87,6 +102,13 @@ else
|
|||
$(INSTALL) $^ .
|
||||
endif
|
||||
|
||||
export:: $(STRING_CSRCS)
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(INSTALL) $^ $(srcdir)
|
||||
else
|
||||
$(INSTALL) $^ .
|
||||
endif
|
||||
|
||||
DEFINES += -DXPCOM_GLUE
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,456 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* 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 a small implementation of the nsAString and nsACString.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Peter Annema <jaggernaut@netscape.com>.
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsEmbedString.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
const PRUnichar gCommonEmptyBuffer[1] = { 0 };
|
||||
|
||||
nsEmbedString::nsEmbedString()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
nsEmbedString::nsEmbedString(const char_type* aString)
|
||||
{
|
||||
Init();
|
||||
Assign(aString);
|
||||
}
|
||||
|
||||
nsEmbedString::nsEmbedString(const char_type* aString, size_type aLength)
|
||||
{
|
||||
Init();
|
||||
Assign(aString, aLength);
|
||||
}
|
||||
|
||||
nsEmbedString::nsEmbedString(const nsEmbedString& aString)
|
||||
{
|
||||
Init();
|
||||
Assign(aString);
|
||||
}
|
||||
|
||||
nsEmbedString::nsEmbedString(const abstract_string_type& aReadable)
|
||||
{
|
||||
Init();
|
||||
Assign(aReadable);
|
||||
}
|
||||
|
||||
nsEmbedString::~nsEmbedString()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedString::Init()
|
||||
{
|
||||
mStr = (char_type*)gCommonEmptyBuffer;
|
||||
mLength = 0;
|
||||
mCapacity = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedString::Destroy()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedString::Free()
|
||||
{
|
||||
if (OwnsBuffer())
|
||||
nsMemory::Free(mStr);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedString::Realloc(size_type aNewSize)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
if (OwnsBuffer())
|
||||
{
|
||||
char_type* temp = (char_type*)nsMemory::Realloc(mStr, (aNewSize + 1) * sizeof(char_type));
|
||||
if (temp)
|
||||
{
|
||||
mStr = temp;
|
||||
mCapacity = aNewSize;
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_type* temp = (char_type*)nsMemory::Alloc((aNewSize + 1) * sizeof(char_type));
|
||||
if (temp)
|
||||
{
|
||||
memcpy(temp, mStr, mLength * sizeof(char_type));
|
||||
mStr = temp;
|
||||
mCapacity = aNewSize;
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedString::OwnsBuffer() const
|
||||
{
|
||||
return mStr != (char_type*)gCommonEmptyBuffer;
|
||||
}
|
||||
|
||||
const nsEmbedString::char_type*
|
||||
nsEmbedString::GetReadableFragment(const_fragment_type& aFragment, nsFragmentRequest aRequest, index_type aOffset) const
|
||||
{
|
||||
switch (aRequest) {
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mStr) + mLength;
|
||||
return aFragment.mStart + aOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsEmbedString::char_type*
|
||||
nsEmbedString::GetWritableFragment(fragment_type& aFragment, nsFragmentRequest aRequest, index_type aOffset)
|
||||
{
|
||||
switch (aRequest) {
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mStr) + mLength;
|
||||
return aFragment.mStart + aOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const nsEmbedString::buffer_handle_type*
|
||||
nsEmbedString::GetFlatBufferHandle() const
|
||||
{
|
||||
return NS_REINTERPRET_CAST(const buffer_handle_type*, 1);
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedString::SetLength(size_type aLength)
|
||||
{
|
||||
if (aLength > mCapacity)
|
||||
GrowCapacity(aLength);
|
||||
|
||||
mLength = aLength;
|
||||
if (mStr != (char_type*)gCommonEmptyBuffer)
|
||||
AddNullTerminator();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedString::SetCapacity(size_type aNewCapacity)
|
||||
{
|
||||
if (aNewCapacity)
|
||||
{
|
||||
if (aNewCapacity > mCapacity)
|
||||
GrowCapacity(aNewCapacity);
|
||||
|
||||
// AddNullTerminator(); // doesn't make sense
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy();
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedString::EnsureCapacity(size_type aNewCapacity)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
if (aNewCapacity > mCapacity)
|
||||
{
|
||||
result = Realloc(aNewCapacity);
|
||||
if (result)
|
||||
AddNullTerminator();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedString::GrowCapacity(size_type aNewCapacity)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
if (mCapacity)
|
||||
{
|
||||
size_type newCapacity = mCapacity;
|
||||
while (newCapacity < aNewCapacity)
|
||||
newCapacity <<= 1;
|
||||
aNewCapacity = newCapacity;
|
||||
}
|
||||
|
||||
nsEmbedString temp;
|
||||
result = temp.EnsureCapacity(aNewCapacity);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (mLength)
|
||||
temp.Assign(*this);
|
||||
|
||||
Free();
|
||||
mStr = temp.mStr;
|
||||
temp.mStr = 0;
|
||||
mLength = temp.mLength;
|
||||
mCapacity = temp.mCapacity;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsEmbedCString::nsEmbedCString()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
nsEmbedCString::nsEmbedCString(const char_type* aString)
|
||||
{
|
||||
Init();
|
||||
Assign(aString);
|
||||
}
|
||||
|
||||
nsEmbedCString::nsEmbedCString(const char_type* aString, size_type aLength)
|
||||
{
|
||||
Init();
|
||||
Assign(aString, aLength);
|
||||
}
|
||||
|
||||
nsEmbedCString::nsEmbedCString(const nsEmbedCString& aString)
|
||||
{
|
||||
Init();
|
||||
Assign(aString);
|
||||
}
|
||||
|
||||
nsEmbedCString::nsEmbedCString(const abstract_string_type& aReadable)
|
||||
{
|
||||
Init();
|
||||
Assign(aReadable);
|
||||
}
|
||||
|
||||
nsEmbedCString::~nsEmbedCString()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedCString::Init()
|
||||
{
|
||||
mStr = (char_type*)gCommonEmptyBuffer;
|
||||
mLength = 0;
|
||||
mCapacity = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedCString::Destroy()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedCString::Free()
|
||||
{
|
||||
if (OwnsBuffer())
|
||||
nsMemory::Free(mStr);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedCString::Realloc(size_type aNewSize)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
if (OwnsBuffer())
|
||||
{
|
||||
char_type* temp = (char_type*)nsMemory::Realloc(mStr, (aNewSize + 1) * sizeof(char_type));
|
||||
if (temp)
|
||||
{
|
||||
mStr = temp;
|
||||
mCapacity = aNewSize;
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_type* temp = (char_type*)nsMemory::Alloc((aNewSize + 1) * sizeof(char_type));
|
||||
if (temp)
|
||||
{
|
||||
memcpy(temp, mStr, mLength * sizeof(char_type));
|
||||
mStr = temp;
|
||||
mCapacity = aNewSize;
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedCString::OwnsBuffer() const
|
||||
{
|
||||
return mStr != (char_type*)gCommonEmptyBuffer;
|
||||
}
|
||||
|
||||
const nsEmbedCString::char_type*
|
||||
nsEmbedCString::GetReadableFragment(const_fragment_type& aFragment, nsFragmentRequest aRequest, index_type aOffset) const
|
||||
{
|
||||
switch (aRequest) {
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mStr) + mLength;
|
||||
return aFragment.mStart + aOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsEmbedCString::char_type*
|
||||
nsEmbedCString::GetWritableFragment(fragment_type& aFragment, nsFragmentRequest aRequest, index_type aOffset)
|
||||
{
|
||||
switch (aRequest) {
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mStr) + mLength;
|
||||
return aFragment.mStart + aOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const nsEmbedCString::buffer_handle_type*
|
||||
nsEmbedCString::GetFlatBufferHandle() const
|
||||
{
|
||||
return NS_REINTERPRET_CAST(const buffer_handle_type*, 1);
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedCString::SetLength(size_type aLength)
|
||||
{
|
||||
if (aLength > mCapacity)
|
||||
GrowCapacity(aLength);
|
||||
|
||||
mLength = aLength;
|
||||
if (mStr != (char_type*)gCommonEmptyBuffer)
|
||||
AddNullTerminator();
|
||||
}
|
||||
|
||||
void
|
||||
nsEmbedCString::SetCapacity(size_type aNewCapacity)
|
||||
{
|
||||
if (aNewCapacity)
|
||||
{
|
||||
if (aNewCapacity > mCapacity)
|
||||
GrowCapacity(aNewCapacity);
|
||||
|
||||
// AddNullTerminator(); // doesn't make sense
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy();
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedCString::EnsureCapacity(size_type aNewCapacity)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
if (aNewCapacity > mCapacity)
|
||||
{
|
||||
result = Realloc(aNewCapacity);
|
||||
if (result)
|
||||
AddNullTerminator();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEmbedCString::GrowCapacity(size_type aNewCapacity)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
if (mCapacity)
|
||||
{
|
||||
size_type newCapacity = mCapacity;
|
||||
while (newCapacity < aNewCapacity)
|
||||
newCapacity <<= 1;
|
||||
aNewCapacity = newCapacity;
|
||||
}
|
||||
|
||||
nsEmbedCString temp;
|
||||
result = temp.EnsureCapacity(aNewCapacity);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (mLength)
|
||||
temp.Assign(*this);
|
||||
|
||||
Free();
|
||||
mStr = temp.mStr;
|
||||
temp.mStr = 0;
|
||||
mLength = temp.mLength;
|
||||
mCapacity = temp.mCapacity;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -317,8 +317,6 @@ interface nsIFile : nsISupports
|
|||
};
|
||||
|
||||
%{C++
|
||||
#define NS_FILE_CONTRACTID "@mozilla.org/file;1"
|
||||
#define NS_FILE_CLASSNAME "File Specification"
|
||||
#ifndef MOZILLA_STRICT_API
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#endif
|
||||
|
|
|
@ -170,8 +170,3 @@ interface nsILocalFile : nsIFile
|
|||
void setRelativeDescriptor(in nsILocalFile fromFile, in ACString relativeDesc);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_LOCAL_FILE_CONTRACTID "@mozilla.org/file/local;1"
|
||||
#define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
|
||||
|
||||
%}
|
||||
|
|
|
@ -63,15 +63,11 @@ EXTRA_COMPONENTS = nsSample.js
|
|||
|
||||
# seperate libraries linked in.
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(DIST)/lib/$(LIB_PREFIX)string_s.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)string_obsolete_s.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
LIBS = \
|
||||
$(DIST)/lib/$(LIB_PREFIX)string_s.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)string_obsolete_s.$(LIB_SUFFIX) \
|
||||
$(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
|
|
@ -47,16 +47,12 @@
|
|||
|
||||
#include "nsSample.h"
|
||||
#include "nsMemory.h"
|
||||
#ifdef XPCOM_GLUE
|
||||
#include "nsXPCOMGlue.h"
|
||||
#endif
|
||||
|
||||
#include "nsEmbedString.h"
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsSampleImpl::nsSampleImpl() : mValue(nsnull)
|
||||
{
|
||||
#ifdef XPCOM_GLUE
|
||||
XPCOMGlueStartup("XPCOMComponentGlue");
|
||||
#endif
|
||||
NS_INIT_ISUPPORTS();
|
||||
mValue = (char*)nsMemory::Clone("initial value", 14);
|
||||
}
|
||||
|
@ -65,10 +61,6 @@ nsSampleImpl::~nsSampleImpl()
|
|||
{
|
||||
if (mValue)
|
||||
nsMemory::Free(mValue);
|
||||
|
||||
#ifdef XPCOM_GLUE
|
||||
XPCOMGlueShutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,6 +142,12 @@ nsSampleImpl::Poke(const char* aValue)
|
|||
return SetValue((char*) aValue);
|
||||
}
|
||||
|
||||
|
||||
static void GetStringValue(nsACString& aValue)
|
||||
{
|
||||
aValue.Assign("GetValue");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSampleImpl::WriteValue(const char* aPrefix)
|
||||
{
|
||||
|
@ -158,5 +156,27 @@ nsSampleImpl::WriteValue(const char* aPrefix)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
printf("%s %s\n", aPrefix, mValue);
|
||||
|
||||
// This next part illustrates the nsEmbedString:
|
||||
nsEmbedString foopy;
|
||||
foopy.Append(PRUnichar('f'));
|
||||
foopy.Append(PRUnichar('o'));
|
||||
foopy.Append(PRUnichar('o'));
|
||||
foopy.Append(PRUnichar('p'));
|
||||
foopy.Append(PRUnichar('y'));
|
||||
|
||||
const PRUnichar* f = foopy.get();
|
||||
PRUint32 l = foopy.Length();
|
||||
printf("%c%c%c%c%c %d\n", char(f[0]), char(f[1]), char(f[2]), char(f[3]), char(f[4]), l);
|
||||
|
||||
nsEmbedCString foopy2;
|
||||
GetStringValue(foopy2);
|
||||
|
||||
//foopy2.Append(NS_LITERAL_CSTRING("foopy"));
|
||||
const char* f2 = foopy2.get();
|
||||
PRUint32 l2 = foopy2.Length();
|
||||
|
||||
printf("%s %d\n", f2, l2);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
#ifdef XPCOM_GLUE
|
||||
#include "nsXPCOMGlue.h"
|
||||
#include "nsMemory.h"
|
||||
#endif
|
||||
|
||||
#define NS_SAMPLE_CONTRACTID "@mozilla.org/sample;1"
|
||||
|
@ -114,8 +115,14 @@ main(void)
|
|||
return -3;
|
||||
}
|
||||
printf("Set value to: %s\n", testValue);
|
||||
#ifndef XPCOM_GLUE
|
||||
nsXPIDLCString str;
|
||||
rv = mysample->GetValue(getter_Copies(str));
|
||||
#else
|
||||
char *str;
|
||||
rv = mysample->GetValue(&str);
|
||||
#endif
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
printf("ERROR: Calling nsISample::GetValue() [%x]\n", rv);
|
||||
|
@ -127,6 +134,9 @@ main(void)
|
|||
return -4;
|
||||
}
|
||||
|
||||
#ifdef XPCOM_GLUE
|
||||
nsMemory::Free(str);
|
||||
#endif
|
||||
rv = mysample->WriteValue("Final print :");
|
||||
printf("Test passed.\n");
|
||||
|
||||
|
|
|
@ -30,13 +30,17 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MODULE = string
|
||||
|
||||
SDK_HEADERS = \
|
||||
nsAString.h \
|
||||
nsBufferHandle.h \
|
||||
nsStringFragment.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsAFlatString.h \
|
||||
nsAlgorithm.h \
|
||||
nsASingleFragmentString.h \
|
||||
nsAString.h \
|
||||
nsAStringGenerator.h \
|
||||
nsBufferHandle.h \
|
||||
nsBufferHandleUtils.h \
|
||||
nsCharTraits.h \
|
||||
nsDependentConcatenation.h \
|
||||
|
@ -51,7 +55,6 @@ EXPORTS = \
|
|||
nsSharedBufferList.h \
|
||||
nsSlidingString.h \
|
||||
nsStringDefines.h \
|
||||
nsStringFragment.h \
|
||||
nsStringFwd.h \
|
||||
nsStringIterator.h \
|
||||
nsStringIteratorUtils.h \
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "nsAString.h"
|
||||
#include "nsDependentSubstring.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "plstr.h"
|
||||
|
||||
|
||||
int
|
||||
|
@ -520,7 +520,12 @@ nsDefaultCStringComparator::operator()( char_type lhs, char_type rhs ) const
|
|||
int
|
||||
nsCaseInsensitiveCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
|
||||
{
|
||||
return nsCRT::strncasecmp(lhs, rhs, aLength);
|
||||
PRInt32 result=PRInt32(PL_strncasecmp(lhs, rhs, aLength));
|
||||
//Egads. PL_strncasecmp is returning *very* negative numbers.
|
||||
//Some folks expect -1,0,1, so let's temper its enthusiasm.
|
||||
if (result<0)
|
||||
result=-1;
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -268,7 +268,7 @@ DeletionTest(const char* creationPath, const char* appendPath, PRBool recursive)
|
|||
{
|
||||
nsCOMPtr<nsILocalFile> file;
|
||||
nsresult rv =
|
||||
nsComponentManager::CreateInstance(NS_FILE_CONTRACTID, NULL,
|
||||
nsComponentManager::CreateInstance(NS_LOCAL_FILE_CONTRACTID, NULL,
|
||||
NS_GET_IID(nsILocalFile),
|
||||
(void**)getter_AddRefs(file));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче