Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
258dc9fead This commit was manufactured by cvs2svn to create branch 'src'.
git-svn-id: svn://10.0.0.236/branches/src@33658 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-03 23:10:01 +00:00
244 changed files with 18627 additions and 41404 deletions

View File

@@ -1,37 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src obsolete
#ifdef ENABLE_TESTS
#DIRS += \
# tests
#endif
include $(topsrcdir)/config/rules.mk

View File

@@ -1,29 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

View File

@@ -1,29 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
/*
* 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)
*/
/*
* Mac build settings for the release string library
*/
#include "MacPrefix.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

View File

@@ -1,30 +0,0 @@
/*
* 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)
*/
/*
* Mac build settings for the debug string library
*/
#include "MacPrefix_debug.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

Binary file not shown.

View File

@@ -1,34 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..
DIRS= public \
src \
obsolete \
#!if !defined(DISABLE_TESTS)
# tests \
#!endif
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,26 +0,0 @@
#
# 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)
#
nsStr.h
nsString.h
nsString2.h

View File

@@ -1,58 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
LIBRARY_NAME = string_obsolete_s
REQUIRES = unicharutil xpcom
CPPSRCS = \
nsStr.cpp \
nsString.cpp \
nsString2.cpp \
$(NULL)
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
# Force use of PIC
FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_COM -D_IMPL_NS_BASE

View File

@@ -1,35 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">original string implementations soon to be replaced (the names you are using will still be good)</span></h1>
<p>
<span class="LXRLONGDESC">These are the original string implementations by rickg and others.
Most of the code here will be made obsolete by the new shared-buffer string (see bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=53065">#53065</a>).
For the most part, this change is intended to be transparent to clients.
The type names you are using for strings now, e.g., nsString, nsAutoString, nsXPIDLString, will still be good,
they will just refer to better, but compatible, implementations.
If you're interested in learning how strings work, you probably want to start with
<a href="http://lxr.mozilla.org/seamonkey/source/string/public/nsAReadableString.h">nsAReadableString</a>.</span>
</p>
</body>
</html>

View File

@@ -1,994 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
/* bufferRoutines.h --- rickg's original string manipulation underpinnings;
this code will be made obsolete by the new shared-buffer string (see bug #53065)
*/
#ifndef _BUFFERROUTINES_H
#define _BUFFERROUTINES_H
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/******************************************************************************************
MODULE NOTES:
This file contains the workhorse copy and shift functions used in nsStrStruct.
Ultimately, I plan to make the function pointers in this system available for
use by external modules. They'll be able to install their own "handlers".
Not so, today though.
*******************************************************************************************/
#include "nsCRT.h"
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
#include "nsUnicharUtilCIID.h"
#include "nsIServiceManager.h"
#include "nsICaseConversion.h"
#endif
#endif /* XPCOM_STANDALONE */
#define KSHIFTLEFT (0)
#define KSHIFTRIGHT (1)
// uncomment the following line to caught nsString char* casting problem
//#define DEBUG_ILLEGAL_CAST_UP
//#define DEBUG_ILLEGAL_CAST_DOWN
#if defined(DEBUG_ILLEGAL_CAST_UP) || defined(DEBUG_ILLEGAL_CAST_DOWN)
static PRBool track_illegal = PR_TRUE;
static PRBool track_latin1 = PR_TRUE;
#ifdef XP_UNIX
#include "nsTraceRefcnt.h"
class CTraceFile {
public:
CTraceFile() {
mFile = fopen("nsStringTrace.txt" , "a+");
}
~CTraceFile() {
fflush(mFile);
fclose(mFile);
}
void ReportCastUp(const char* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT= %s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const char* s=data;
while(*s) {
if(*s & 0x80) {
fprintf(mFile, "[%2X]", (char)*s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
void ReportCastDown(const PRUnichar* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT=%s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const PRUnichar* s=data;
while(*s) {
if(*s & 0xFF80) {
fprintf(mFile, "\\u%X", *s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
private:
FILE* mFile;
};
static CTraceFile gTrace;
#define TRACE_ILLEGAL_CAST_UP(c, s, m) if(!(c)) gTrace.ReportCastUp(s,m);
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) if(!(c)) gTrace.ReportCastDown(s,m);
#else // XP_UNIX
#define TRACE_ILLEGAL_CAST_UP(c, s, m) NS_ASSERTION((c), (m))
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) NS_ASSERTION((c), (m))
#endif //XP_UNIX
#endif
inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) {
return ((PRUnichar*)aString)[anIndex];
}
inline PRUnichar GetCharAt(const char* aString,PRUint32 anIndex) {
return (PRUnichar)aString[anIndex];
}
//----------------------------------------------------------------------------------------
//
// This set of methods is used to shift the contents of a char buffer.
// The functions are differentiated by shift direction and the underlying charsize.
//
/**
* This method shifts single byte characters left by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where left-shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anOffset;
char* src = aDest+anOffset+aCount;
memmove(dst,src,aLength-(aCount+anOffset));
}
/**
* This method shifts single byte characters right by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* src = aDest+anOffset;
char* dst = aDest+anOffset+aCount;
memmove(dst,src,aLength-anOffset);
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftDoubleCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftDoubleCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* dst = root+anOffset;
PRUnichar* src = root+anOffset+aCount;
memmove(dst,src,(aLength-(aCount+anOffset))*sizeof(PRUnichar));
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftDoubleCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftDoubleCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* src = root+anOffset;
PRUnichar* dst = root+anOffset+aCount;
memmove(dst,src,sizeof(PRUnichar)*(aLength-anOffset));
}
typedef void (*ShiftChars)(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
ShiftChars gShiftChars[2][2]= {
{&ShiftCharsLeft,&ShiftCharsRight},
{&ShiftDoubleCharsLeft,&ShiftDoubleCharsRight}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to copy one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* Going 1 to 1 is easy, since we assume ascii. No conversions are necessary.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars1To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anDestOffset;
char* src = (char*)aSource+anOffset;
memcpy(dst,src,aCount);
}
/**
* Going 1 to 2 requires a conversion from ascii to unicode. This can be expensive.
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars1To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
const unsigned char* first= (const unsigned char*)aSource+anOffset;
const unsigned char* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_UP
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
*to=(PRUnichar)(*first);
#ifdef DEBUG_ILLEGAL_CAST_UP
if(track_illegal && track_latin1 && ((*to)& 0x80))
illegal= PR_TRUE;
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_UP
TRACE_ILLEGAL_CAST_UP((!illegal), aSource, "illegal cast up in CopyChars1To2");
#endif
}
/**
* Going 2 to 1 requires a conversion from unicode down to ascii. This can be lossy.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* to = aDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
const PRUnichar* first= theSource+anOffset;
const PRUnichar* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_DOWN
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
if(*first<256)
*to=(char)*first;
else {
*to='.';
NS_ASSERTION( (*first < 256), "data in U+0100-U+FFFF will be lost");
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
if(track_illegal) {
if(track_latin1) {
if(*first & 0xFF80)
illegal = PR_TRUE;
} else {
if(*first & 0xFF00)
illegal = PR_TRUE;
} // track_latin1
} // track_illegal
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
TRACE_ILLEGAL_CAST_DOWN((!illegal), theSource, "illegal cast down in CopyChars2To1");
#endif
}
/**
* Going 2 to 2 is fast and efficient.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars2To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
PRUnichar* from= theSource+anOffset;
memcpy((void*)to,(void*)from,aCount*sizeof(PRUnichar));
}
//--------------------------------------------------------------------------------------
typedef void (*CopyChars)(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
CopyChars gCopyChars[2][2]={
{&CopyChars1To1,&CopyChars1To2},
{&CopyChars2To1,&CopyChars2To2}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to search a buffer looking for a char.
//
/**
* This methods cans the given buffer for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* left= aDest+anOffset;
const char* last= left+aCount;
const char* max = aDest+aDestLength;
const char* end = (last<max) ? last : max;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-aDest;
++left;
}
}
else {
PRInt32 theMax = end-left;
if(0<theMax) {
unsigned char theChar = (unsigned char) aChar;
const char* result=(const char*)memchr(left, (int)theChar, theMax);
if(result) {
return result-aDest;
}
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* left = root+anOffset;
const PRUnichar* last = left+aCount;
const PRUnichar* max = root+aDestLength;
const PRUnichar* end = (last<max) ? last : max;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-root;
++left;
}
}
else {
while(left<end){
if(*left==aChar)
return (left-root);
++left;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer (in reverse) for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = PRInt32(aDestLength);
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* rightmost = aDest+anOffset;
const char* min = rightmost-aCount+1;
const char* leftmost = (min<aDest) ? aDest: min;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
else {
char theChar=(char)aChar;
while(leftmost<=rightmost){
if((*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = PRInt32(aDestLength);
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* rightmost = root+anOffset;
const PRUnichar* min = rightmost-aCount+1;
const PRUnichar* leftmost = (min<root) ? root: min;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-root;
--rightmost;
}
}
else {
while(leftmost<=rightmost){
if((*rightmost)==aChar)
return rightmost-root;
--rightmost;
}
}
}
}
return kNotFound;
}
typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount);
FindChars gFindChars[]={&FindChar1,&FindChar2};
FindChars gRFindChars[]={&RFindChar1,&RFindChar2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to compare one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp(aStr1,aStr2,aCount);
else result=memcmp(aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
else result=nsCRT::strncmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
return result;
}
typedef PRInt32 (*CompareChars)(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
CompareChars gCompare[2][2]={
{&Compare1To1,&Compare1To2},
{&Compare2To1,&Compare2To2},
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to convert the case of strings...
//
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper);
PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper){
PRInt32 result=0;
typedef char chartype;
chartype* cp = (chartype*)aString;
chartype* end = cp + aCount-1;
while (cp <= end) {
chartype ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = chartype('A' + (ch - 'a'));
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = chartype('a' + (ch - 'A'));
}
}
cp++;
}
return result;
}
//----------------------------------------------------------------------------------------
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
class HandleCaseConversionShutdown3 : public nsIShutdownListener {
public :
NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service);
HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); }
virtual ~HandleCaseConversionShutdown3(void) {}
NS_DECL_ISUPPORTS
};
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
static nsICaseConversion * gCaseConv = 0;
NS_IMPL_ISUPPORTS1(HandleCaseConversionShutdown3, nsIShutdownListener);
nsresult HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) {
if (cid.Equals(kUnicharUtilCID)) {
NS_ASSERTION(service == gCaseConv, "wrong service!");
if(gCaseConv){
gCaseConv->Release();
gCaseConv = 0;
}
}
return NS_OK;
}
class CCaseConversionServiceInitializer {
public:
CCaseConversionServiceInitializer(){
HandleCaseConversionShutdown3* listener =
new HandleCaseConversionShutdown3();
if(listener){
nsServiceManager::GetService(kUnicharUtilCID, NS_GET_IID(nsICaseConversion),(nsISupports**) &gCaseConv, listener);
}
}
};
#endif
#endif /* XPCOM_STANDALONE */
//----------------------------------------------------------------------------------------
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper);
PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper){
PRUnichar* cp = (PRUnichar*)aString;
PRUnichar* end = cp + aCount-1;
PRInt32 result=0;
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
static CCaseConversionServiceInitializer gCaseConversionServiceInitializer;
// I18N code begin
if(gCaseConv) {
nsresult err=(aToUpper) ? gCaseConv->ToUpper(cp, cp, aCount) : gCaseConv->ToLower(cp, cp, aCount);
if(NS_SUCCEEDED(err))
return 0;
}
// I18N code end
#endif
#endif /* XPCOM_STANDALONE */
while (cp <= end) {
PRUnichar ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = PRUnichar('A' + (ch - 'a'));
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = PRUnichar('a' + (ch - 'A'));
}
}
cp++;
}
return result;
}
typedef PRInt32 (*CaseConverters)(char*,PRUint32,PRBool);
CaseConverters gCaseConverters[]={&ConvertCase1,&ConvertCase2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used compress char sequences in a buffer...
//
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
char* from = aString;
char* end = aString + aLength;
char* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
char theChar = *from++;
*to++=theChar; //always copy this char...
if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - aString;
}
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* from = (PRUnichar*)aString;
PRUnichar* end = from + aLength;
PRUnichar* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
PRUnichar theChar = *from++;
*to++=theChar; //always copy this char...
if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*CompressChars)(char* aString,PRUint32 aCount,const char* aSet);
CompressChars gCompressChars[]={&CompressChars1,&CompressChars2};
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars1(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 StripChars1(char* aString,PRUint32 aLength,const char* aSet){
char* to = aString;
char* from = aString-1;
char* end = aString + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
char theChar = *from;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
}
}
*to = 0;
}
return to - (char*)aString;
}
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars2(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 StripChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* to = (PRUnichar*)aString;
PRUnichar* from = (PRUnichar*)aString-1;
PRUnichar* end = to + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
PRUnichar theChar = *from;
//Note the test for ascii range below. If you have a real unicode char,
//and you're searching for chars in the (given) ascii string, there's no
//point in doing the real search since it's out of the ascii range.
if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
*to++ = theChar;
}
}
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*StripChars)(char* aString,PRUint32 aCount,const char* aSet);
StripChars gStripChars[]={&StripChars1,&StripChars2};
#endif

View File

@@ -1,49 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..\..
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
$(NULL)
LIBRARY_NAME=string_obsolete_s
LIBRARY=.\$(OBJDIR)\$(LIBRARY_NAME).lib
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
CPP_OBJS = \
.\$(OBJDIR)\nsStr.obj \
.\$(OBJDIR)\nsString.obj \
.\$(OBJDIR)\nsString2.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,921 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
#include "nsStr.h"
#include "bufferRoutines.h"
#include <stdio.h> //only used for printf
#include "nsCRT.h"
#include "nsDeque.h"
/******************************************************************************************
MODULE NOTES:
This file contains the nsStr data structure.
This general purpose buffer management class is used as the basis for our strings.
It's benefits include:
1. An efficient set of library style functions for manipulating nsStrs
2. Support for 1 and 2 byte character strings (which can easily be increased to n)
3. Unicode awareness and interoperability.
*******************************************************************************************/
//static const char* kCallFindChar = "For better performance, call FindChar() for targets whose length==1.";
//static const char* kCallRFindChar = "For better performance, call RFindChar() for targets whose length==1.";
static const PRUnichar gCommonEmptyBuffer[1] = {0};
static PRBool gStringAcquiredMemory = PR_TRUE;
/**
* This method initializes all the members of the nsStr structure
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=(char*)gCommonEmptyBuffer;
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
}
/**
* This method initializes all the members of the nsStr structure
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
}
/**
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Destroy(nsStr& aDest) {
if((aDest.mStr) && (aDest.mStr!=(char*)gCommonEmptyBuffer)) {
Free(aDest);
}
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents are not preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aString.mCapacity) {
result=Realloc(aString,aNewLength);
if(aString.mStr)
AddNullTerminator(aString);
}
return result;
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents ARE preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
// the new strategy is, allocate exact size, double on grows
if ( aDest.mCapacity ) {
PRUint32 newCapacity = aDest.mCapacity;
while ( newCapacity < aNewLength )
newCapacity <<= 1;
aNewLength = newCapacity;
}
#endif
result=EnsureCapacity(theTempStr,aNewLength);
if(result) {
if(aDest.mLength) {
StrAppend(theTempStr,aDest,0,aDest.mLength);
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
return result;
}
/**
* Replaces the contents of aDest with aSource, up to aCount of chars.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed.
* @param aSource is where chars are copied from
* @param aCount is the number of chars copied from aSource
*/
void nsStr::StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(&aDest!=&aSource){
StrTruncate(aDest,0);
StrAppend(aDest,aSource,anOffset,aCount);
}
}
/**
* This method appends the given nsStr to this one. Note that we have to
* pay attention to the underlying char-size of both structs.
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aSource is where char are copied from
* @aCount is the number of bytes to be copied
*/
void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(anOffset<aSource.mLength){
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
if(0<theLength){
PRBool isBigEnough=PR_TRUE;
if(aDest.mLength+theLength > aDest.mCapacity) {
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
}
if(isBigEnough) {
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
}
}
/**
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed
* @param aDestOffset is where in aDest the insertion is to occur
* @param aSource is where chars are copied from
* @param aSrcOffset is where in aSource chars are copied from
* @param aCount is the number of chars from aSource to be inserted into aDest
*/
void nsStr::StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
if(0<aSource.mLength){
if(aDest.mLength){
if(aDestOffset<aDest.mLength){
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
if(aSrcOffset<aSource.mLength) {
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
if(isBigEnough) {
if(aDestOffset) {
StrAppend(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
}
StrAppend(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
PRUint32 theRemains=aDest.mLength-aDestOffset;
if(theRemains) {
StrAppend(theTempStr,aDest,aDestOffset,theRemains); //next copy rightmost data
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
else {
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
}
//finally, make sure to update the string length...
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}//if
//else nothing to do!
}
else StrAppend(aDest,aSource,0,aCount);
}
else StrAppend(aDest,aSource,0,aCount);
}
}
/**
* This method deletes up to aCount chars from aDest
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aDestOffset is where in aDest deletion is to occur
* @param aCount is the number of chars to be deleted in aDest
*/
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
if(aDestOffset<aDest.mLength){
PRUint32 theDelta=aDest.mLength-aDestOffset;
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
if(aDestOffset+theLength<aDest.mLength) {
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
else StrTruncate(aDest,aDestOffset);
}//if
}
/**
* This method truncates the given nsStr at given offset
* @update gess10/30/98
* @param aDest is the nsStr to be truncated
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::StrTruncate(nsStr& aDest,PRUint32 aDestOffset){
if(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
/**
* This method forces the given string to upper or lowercase
* @update gess1/7/99
* @param aDest is the string you're going to change
* @param aToUpper: if TRUE, then we go uppercase, otherwise we go lowercase
* @return
*/
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
// somehow UnicharUtil return failed, fallback to the old ascii only code
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
}
/**
* This method removes characters from the given set from this string.
* NOTE: aSet is a char*, and it's length is computed using strlen, which assumes null termination.
*
* @update gess 11/7/99
* @param aDest
* @param aSet
* @param aEliminateLeading
* @param aEliminateTrailing
* @return nothing
*/
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
if((aDest.mLength>0) && aSet){
PRInt32 theIndex=-1;
PRInt32 theMax=aDest.mLength;
PRInt32 theSetLen=nsCRT::strlen(aSet);
if(aEliminateLeading) {
while(++theIndex<=theMax) {
PRUnichar theChar=GetCharAt(aDest,theIndex);
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound==thePos)
break;
}
if(0<theIndex) {
if(theIndex<theMax) {
Delete(aDest,0,theIndex);
}
else StrTruncate(aDest,0);
}
}
if(aEliminateTrailing) {
theIndex=aDest.mLength;
PRInt32 theNewLen=theIndex;
while(--theIndex>=0) {
PRUnichar theChar=GetCharAt(aDest,theIndex); //read at end now...
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound<thePos)
theNewLen=theIndex;
else break;
}
if(theNewLen<theMax) {
StrTruncate(aDest,theNewLen);
}
}
}
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=gCompressChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::StripChars(nsStr& aDest,const char* aSet){
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
}
/**************************************************************
Searching methods...
**************************************************************/
/**
* This searches aDest for a given substring
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tells us how many iterations to make from offset; -1 means the full length of the string
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
if(0<=theMaxPos) {
if(anOffset<0)
anOffset=0;
if((0<aDest.mLength) && (anOffset<=theMaxPos) && (aTarget.mLength)) {
if(aCount<0)
aCount = MaxInt(theMaxPos,1);
if(0<aCount) {
PRInt32 aDelta= (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* left = root+(anOffset*aDelta);
const char* last = left+((aCount)*aDelta);
const char* max = root+(theMaxPos*aDelta);
const char* right = (last<max) ? last : max;
while(left<=right){
PRInt32 cmp=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(left,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==cmp) {
return (left-root)/aDelta;
}
left+=aDelta;
} //while
} //if
}
} //if
return kNotFound;
}
/**
* This searches aDest for a given character
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tell us how many chars to search from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallFindChar);
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
//Note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if((0<aDest.mLength) && (0<aSet.mLength)){
while(++index<(PRInt32)aDest.mLength) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**************************************************************
Reverse Searching methods...
**************************************************************/
/**
* This searches aDest (in reverse) for a given substring
*
* @update gess 2/18/00
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search (counting from left)
* @param aCount tell us how many iterations to perform from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
if(aCount<0)
aCount = aDest.mLength;
if((0<aDest.mLength) && ((PRUint32)anOffset<aDest.mLength) && (aTarget.mLength)) {
if(0<aCount) {
PRInt32 aDelta = (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* destLast = root+(aDest.mLength*aDelta); //pts to last char in aDest (likely null)
const char* rightmost = root+(anOffset*aDelta);
const char* min = rightmost-((aCount-1)*aDelta);
const char* leftmost = (min<root) ? root: min;
while(leftmost<=rightmost) {
//don't forget to divide by delta in next text (bug found by rhp)...
if(aTarget.mLength<=PRUint32((destLast-rightmost)/aDelta)) {
PRInt32 result=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(rightmost,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==result) {
return (rightmost-root)/aDelta;
}
} //if
rightmost-=aDelta;
} //while
}
}
return kNotFound;
}
/**
* This searches aDest (in reverse) for a given character
*
* @update gess 2/04/00
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search; -1 means start at very end (mLength)
* @param aCount tell us how many iterations to perform from offset; -1 means use full length.
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest (in reverese) for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallRFindChar);
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
//note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if(0<aDest.mLength) {
while(--index>=0) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**
* Compare source and dest strings, up to an (optional max) number of chars
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aCount -- if (-1), then we use length of longer string; if (0<aCount) then it gives the max # of chars to compare
* @param aIgnorecase tells us whether to search with case sensitivity
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
PRInt32 result=0;
if(aCount) {
PRInt32 minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
if(0==minlen) {
if ((aDest.mLength == 0) && (aSource.mLength == 0))
return 0;
if (aDest.mLength == 0)
return -1;
return 1;
}
PRInt32 theCount = (aCount<0) ? minlen: MinInt(aCount,minlen);
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,theCount,aIgnoreCase);
if (0==result) {
if(-1==aCount) {
//Since the caller didn't give us a length to test, and minlen characters matched,
//we have to assume that the longer string is greater.
if (aDest.mLength != aSource.mLength) {
//we think they match, but we've only compared minlen characters.
//if the string lengths are different, then they don't really match.
result = (aDest.mLength<aSource.mLength) ? -1 : 1;
}
} //if
}
}
return result;
}
/**
* Overwrites the contents of dest at offset with contents of aSource
*
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aDestOffset is the offset within aDest where source should be copied
* @return error code
*/
void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
if(aDest.mLength && aSource.mLength) {
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
//if you're here, then both dest and source have valid lengths
//and there's enough room in dest (at offset) to contain source.
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
}
}
}
//----------------------------------------------------------------------------------------
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
static int mAllocCount=0;
mAllocCount++;
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
//we're given the acount value in charunits; now scale up to next multiple.
PRUint32 theNewCapacity=kDefaultStringSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
}
aDest.mCapacity=theNewCapacity++;
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr = (char*)nsMemory::Alloc(theSize);
#else
// the new strategy is, allocate exact size, double on grows
aDest.mCapacity = aCount;
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
#endif
if(aDest.mStr) {
aDest.mOwnsBuffer=1;
gStringAcquiredMemory=PR_TRUE;
}
else gStringAcquiredMemory=PR_FALSE;
return gStringAcquiredMemory;
}
PRBool nsStr::Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
nsMemory::Free(aDest.mStr);
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
return PR_TRUE;
}
return PR_FALSE;
}
PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
nsStr temp;
memcpy(&temp,&aDest,sizeof(aDest));
PRBool result=Alloc(temp,aCount);
if(result) {
Free(aDest);
aDest.mStr=temp.mStr;
aDest.mCapacity=temp.mCapacity;
aDest.mOwnsBuffer=temp.mOwnsBuffer;
}
return result;
}
/**
* Retrieve last memory error
*
* @update gess 10/11/99
* @return memory error (usually returns PR_TRUE)
*/
PRBool nsStr::DidAcquireMemory(void) {
return gStringAcquiredMemory;
}
//----------------------------------------------------------------------------------------
CBufDescriptor::CBufDescriptor(char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_FALSE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_TRUE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_FALSE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_TRUE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
//----------------------------------------------------------------------------------------
PRUint32
nsStr::HashCode(const nsStr& aDest)
{
if (aDest.mCharSize == eTwoByte)
return nsCRT::HashCode(aDest.mUStr);
else
return nsCRT::HashCode(aDest.mStr);
}
#ifdef NS_STR_STATS
#include <ctype.h>
#ifdef XP_MAC
#define isascii(c) ((unsigned)(c) < 0x80)
#endif
void
nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
{
PRInt32 printLen = (PRInt32)aDest.mLength;
if (aDest.mCharSize == eOneByte) {
const char* chars = aDest.mStr;
while (printLen-- && (!truncate || *chars != '\n')) {
fputc(*chars++, out);
}
}
else {
const PRUnichar* chars = aDest.mUStr;
while (printLen-- && (!truncate || *chars != '\n')) {
if (isascii(*chars))
fputc((char)(*chars++), out);
else
fputc('-', out);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// String Usage Statistics Routines
static PLHashTable* gStringInfo = nsnull;
PRLock* gStringInfoLock = nsnull;
PRBool gNoStringInfo = PR_FALSE;
nsStringInfo::nsStringInfo(nsStr& str)
: mCount(0)
{
nsStr::Initialize(mStr, str.mCharSize);
nsStr::StrAssign(mStr, str, 0, -1);
// nsStr::Print(mStr, stdout);
// fputc('\n', stdout);
}
PR_EXTERN(PRHashNumber)
nsStr_Hash(const void* key)
{
nsStr* str = (nsStr*)key;
return nsStr::HashCode(*str);
}
PR_EXTERN(PRIntn)
nsStr_Compare(const void *v1, const void *v2)
{
nsStr* str1 = (nsStr*)v1;
nsStr* str2 = (nsStr*)v2;
return nsStr::StrCompare(*str1, *str2, -1, PR_FALSE) == 0;
}
nsStringInfo*
nsStringInfo::GetInfo(nsStr& str)
{
if (gStringInfo == nsnull) {
gStringInfo = PL_NewHashTable(1024,
nsStr_Hash,
nsStr_Compare,
PL_CompareValues,
NULL, NULL);
gStringInfoLock = PR_NewLock();
}
PR_Lock(gStringInfoLock);
nsStringInfo* info =
(nsStringInfo*)PL_HashTableLookup(gStringInfo, &str);
if (info == NULL) {
gNoStringInfo = PR_TRUE;
info = new nsStringInfo(str);
if (info) {
PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info);
if (e == NULL) {
delete info;
info = NULL;
}
}
gNoStringInfo = PR_FALSE;
}
PR_Unlock(gStringInfoLock);
return info;
}
void
nsStringInfo::Seen(nsStr& str)
{
if (!gNoStringInfo) {
nsStringInfo* info = GetInfo(str);
info->mCount++;
}
}
void
nsStringInfo::Report(FILE* out)
{
if (gStringInfo) {
fprintf(out, "\n== String Stats\n");
PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out);
}
}
PRIntn
nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg)
{
nsStringInfo* entry = (nsStringInfo*)he->value;
FILE* out = (FILE*)arg;
fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength);
nsStr::Print(entry->mStr, out, PR_TRUE);
fputc('\n', out);
return HT_ENUMERATE_NEXT;
}
#endif // NS_STR_STATS
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,532 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsStr.h --- the underlying buffer for rickg's original string implementations;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsStr
#define _nsStr
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/***********************************************************************
MODULE NOTES:
1. There are two philosophies to building string classes:
A. Hide the underlying buffer & offer API's allow indirect iteration
B. Reveal underlying buffer, risk corruption, but gain performance
We chose the option B for performance reasons.
2 Our internal buffer always holds capacity+1 bytes.
The nsStr struct is a simple structure (no methods) that contains
the necessary info to be described as a string. This simple struct
is manipulated by the static methods provided in this class.
(Which effectively makes this a library that works on structs).
There are also object-based versions called nsString and nsAutoString
which use nsStr but makes it look at feel like an object.
***********************************************************************/
/***********************************************************************
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated. However,
since it maintains a length byte, you can store NULL's inside
the string. Just be careful passing such buffers to 3rd party
API's that assume that NULL always terminate the buffer.
2. nsCStrings can be upsampled into nsString without data loss
3. Char searching is faster than string searching. Use char interfaces
if your needs will allow it.
4. It's easy to use the stack for nsAutostring buffer storage (fast too!).
See the CBufDescriptor class in this file.
5. If you don't provide the optional count argument to Append() and Insert(),
the method will assume that the given buffer is terminated by the first
NULL it encounters.
6. Downsampling from nsString to nsCString can be lossy -- avoid it if possible!
7. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to nsMemory::Free().
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsMemory
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenuously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
--- FAQ ---
Q. When should I use nsCString instead of nsString?
A. You should really try to stick with nsString, so that we stay as unicode
compliant as possible. But there are cases where an interface you use requires
a char*. In such cases, it's fair to use nsCString.
Q. I know that my string is going to be a certain size. Can I pre-size my nsString?
A. Yup, here's how:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
Q. Should nsAutoString or nsCAutoString ever live on the heap?
A. That would be counterproductive. The point of nsAutoStrings is to preallocate your
buffers, and to auto-destroy the string when it goes out of scope.
Q. I already have a char*. Can I use the nsString functionality on that buffer?
A. Yes you can -- by using an intermediate class called CBufDescriptor.
The CBufDescriptor class is used to tell nsString about an external buffer (heap or stack) to use
instead of it's own internal buffers. Here's an example:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString/nsCString interfaces. Cool, huh?
Note however that just like any other nsStringXXX use, if you write more data
than will fit in the buffer, a visit to the heap manager will be in order.
Q. What is the simplest way to get from a char* to PRUnichar*?
A. The simplest way is by construction (or assignment):
{
char* theBuf = "hello there";
nsAutoString foo(theBuf);
}
If you don't want the char* to be copied into the nsAutoString, the use a
CBufDescriptor instead.
**********************************************************************************/
#include "nscore.h"
#include "nsMemory.h"
#include <string.h>
#include <stdio.h>
#include "plhash.h"
//----------------------------------------------------------------------------------------
enum eCharSize {eOneByte=0,eTwoByte=1};
#define kDefaultCharSize eTwoByte
#define kRadix10 (10)
#define kRadix16 (16)
#define kAutoDetect (100)
#define kRadixUnknown (kAutoDetect+1)
#define IGNORE_CASE (PR_TRUE)
const PRInt32 kDefaultStringSize = 64;
const PRInt32 kNotFound = -1;
//----------------------------------------------------------------------------------------
class NS_COM CBufDescriptor {
public:
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(PRUnichar* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
char* mBuffer;
eCharSize mCharSize;
PRUint32 mCapacity;
PRInt32 mLength;
PRBool mStackBased;
PRBool mIsConst;
};
//----------------------------------------------------------------------------------------
struct NS_COM nsStr {
nsStr() {
MOZ_COUNT_CTOR(nsStr);
}
~nsStr() {
MOZ_COUNT_DTOR(nsStr);
}
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,eCharSize aCharSize);
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
/**
* This method destroys the given nsStr, and *MAY*
* deallocate it's memory depending on the setting
* of the internal mOwnsBUffer flag.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used to the nsStr
*/
static void Destroy(nsStr& aDest);
/**
* These methods are where memory allocation/reallocation occur.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used on the nsStr
* @return
*/
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
static PRBool GrowCapacity(nsStr& aString,PRUint32 aNewLength);
/**
* These methods are used to append content to the given nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to assign contents of a source string to dest string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to insert content from source string to the dest nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to insert
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
/**
* This method deletes chars from the given str.
* The given allocator may choose to resize the str as well.
*
* @update gess 01/04/99
* @param aDest is the nsStr to be deleted from
* @param aDestOffset tells us where in dest to start deleting
* @param aCount tells us the (max) # of chars to delete
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
/**
* This method is used to truncate the given string.
* The given allocator may choose to resize the str as well (but it's not likely).
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrTruncate(nsStr& aDest,PRUint32 aDestOffset);
/**
* This method is used to perform a case conversion on the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be case shifted
* @param toUpper tells us to go upper vs. lower
*/
static void ChangeCase(nsStr& aDest,PRBool aToUpper);
/**
* This method trims chars (given in aSet) from the edges of given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to remove from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method removes all occurances of chars in given set from aDest
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void StripChars(nsStr& aDest,const char* aSet);
/**
* This method compares the data bewteen two nsStr's
*
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
static PRInt32 StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase);
/**
* These methods scan the given string for 1 or more chars in a given direction
*
* @update gess 01/04/99
* @param aDest is the nsStr to be searched to
* @param aSource (or aChar) is the substr we're looking to find
* @param aIgnoreCase tells us whether to search in a case-sensitive manner
* @param anOffset tells us where in the dest string to start searching
* @return the index of the source (substr) in dest, or -1 (kNotFound) if not found.
*/
static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
static PRBool DidAcquireMemory(void);
/**
* Returns a hash code for the string for use in a PLHashTable.
*/
static PRUint32 HashCode(const nsStr& aDest);
#ifdef NS_STR_STATS
/**
* Prints an nsStr. If truncate is true, the string is only printed up to
* the first newline. (Note: The current implementation doesn't handle
* non-ascii unicode characters.)
*/
static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE);
#endif
PRUint32 mLength;
PRUint32 mCapacity;
eCharSize mCharSize;
PRBool mOwnsBuffer;
union {
char* mStr;
PRUnichar* mUStr;
};
private:
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
static PRBool Free(nsStr& aString);
};
/**************************************************************
A couple of tiny helper methods used in the string classes.
**************************************************************/
inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt1 : anInt2;
}
inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt2 : anInt1;
}
inline void AddNullTerminator(nsStr& aDest) {
if(eTwoByte==aDest.mCharSize)
aDest.mUStr[aDest.mLength]=0;
else aDest.mStr[aDest.mLength]=0;
}
/**
* Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
*
* Return the given buffer to the heap manager. Calls allocator::Free()
* @return string length
*/
inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
/**
* This method is used to access a given char in the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param anIndex tells us where in dest to get the char from
* @return the given char, or 0 if anIndex is out of range
*/
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
if(anIndex<aDest.mLength) {
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
}//if
return 0;
}
#ifdef NS_STR_STATS
class nsStringInfo {
public:
nsStringInfo(nsStr& str);
~nsStringInfo() {}
static nsStringInfo* GetInfo(nsStr& str);
static void Seen(nsStr& str);
static void Report(FILE* out = stdout);
static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg);
protected:
nsStr mStr;
PRUint32 mCount;
};
#define NSSTR_SEEN(str) nsStringInfo::Seen(str)
#else // !NS_STR_STATS
#define NSSTR_SEEN(str) /* nothing */
#endif // !NS_STR_STATS
#endif // _nsStr

File diff suppressed because it is too large Load Diff

View File

@@ -1,551 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString.h --- rickg's original strings of 1-byte chars, |nsCString| and |nsCAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsCString_
#define _nsCString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "nsString2.h"
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsStr.h"
#include "nsIAtom.h"
#include "nsAString.h"
#include "nsXPIDLString.h"
/* this file will one day be _only_ a compatibility header for clients using the names
|ns[C]String| et al ... which we probably want to support forever.
In the mean time, people are used to getting the names |nsAReadable[C]String| and friends
from here as well; so we must continue to include the other compatibility headers
even though we don't use them ourself.
*/
#include "nsAWritableString.h"
// for compatibility
class NS_COM nsCString :
public nsAFlatCString,
public nsStr {
protected:
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const;
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
public:
virtual const char* get() const { return mStr; }
public:
/**
* Default constructor.
*/
nsCString();
/**
* This is our copy constructor
* @param reference to another nsCString
*/
nsCString(const nsCString& aString);
explicit nsCString( const nsACString& );
explicit nsCString(const char*);
nsCString(const char*, PRInt32);
/**
* Destructor
*
*/
virtual ~nsCString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string capacity
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**********************************************************************
Accessor methods...
*********************************************************************/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsCString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsCString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars(const char* aSet);
void StripChar(PRUnichar aChar,PRInt32 anOffset=0);
void StripChar(char aChar,PRInt32 anOffset=0) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
void ReplaceChar(const char* aSet,PRUnichar aNewChar);
void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue);
void ReplaceSubstring(const char* aTarget,const char* aNewValue);
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsCString that is a clone
* of this string.
*
*/
nsCString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return this
*/
nsCString& operator=( const nsCString& aString ) { Assign(aString); return *this; }
nsCString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
//nsCString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCString& operator=( char aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(const PRUnichar*,PRInt32=-1);
void AssignWithConversion( const nsString& aString );
void AssignWithConversion( const nsAString& aString );
void AssignWithConversion(PRUnichar);
/*
* Appends n characters from given string to this,
*
* @param aString is the source to be appended to this
* @param aCount -- number of chars to copy; -1 tells us to compute the strlen for you
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return number of chars copied
*/
void AppendWithConversion(const nsString&, PRInt32=-1);
void AppendWithConversion(PRUnichar aChar);
void AppendWithConversion( const nsAString& aString );
void AppendWithConversion(const PRUnichar*, PRInt32=-1);
// Why no |AppendWithConversion(const PRUnichar*, PRInt32)|? --- now I know, because implicit construction hid the need for this routine
void AppendInt(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
void AppendFloat( double aFloat );
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
// Why no |InsertWithConversion(PRUnichar*)|?
#if 0
virtual void do_AppendFromReadable( const nsACString& );
virtual void do_InsertFromReadable( const nsACString&, PRUint32 );
#endif
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRBool
EqualsWithConversion(const nsXPIDLString &aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return EqualsWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const nsAFlatCString& aString) const
{
return EqualsIgnoreCase(aString.get(), aString.Length());
}
PRBool EqualsIgnoreCase(const nsAFlatCString& aString, PRInt32 aCount) const
{
return EqualsIgnoreCase(aString.get(), aCount);
}
void DebugDump(void) const;
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( PRUnichar );
void AssignWithConversion( char );
void AssignWithConversion( const char*, PRInt32=-1 );
void AppendWithConversion( char );
void InsertWithConversion( char, PRUint32 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsCString, char)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCString, char)
extern NS_COM int fputs(const nsCString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsCString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsCAutoString : public nsCString {
public:
virtual ~nsCAutoString();
nsCAutoString();
explicit nsCAutoString(const nsCString& );
explicit nsCAutoString(const nsACString& aString);
explicit nsCAutoString(const char* aString);
nsCAutoString(const char* aString,PRInt32 aLength);
explicit nsCAutoString(const CBufDescriptor& aBuffer);
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
public:
nsCAutoString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
// nsCAutoString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCAutoString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCAutoString& operator=( char aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCAutoString, char)
/**
* A helper class that converts a UCS2 string to UTF8
*/
class NS_COM NS_ConvertUCS2toUTF8
: public nsCAutoString
/*
...
*/
{
public:
explicit
NS_ConvertUCS2toUTF8( const PRUnichar* aString )
{
Append( aString, ~PRUint32(0) /* MAXINT */);
}
NS_ConvertUCS2toUTF8( const PRUnichar* aString, PRUint32 aLength )
{
Append( aString, aLength );
}
explicit
NS_ConvertUCS2toUTF8( PRUnichar aChar )
{
Append( &aChar, 1 );
}
explicit NS_ConvertUCS2toUTF8( const nsAString& aString );
protected:
void Append( const PRUnichar* aString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertUCS2toUTF8( char );
operator const char*() const; // use |get()|
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,681 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString2.h --- rickg's original strings of 2-byte chars, |nsString| and |nsAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsString_
#define _nsString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsString.h"
#include "nsIAtom.h"
#include "nsStr.h"
#include "nsCRT.h"
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#include "nsXPIDLString.h"
#ifdef STANDALONE_MI_STRING_TESTS
class nsAFlatString { public: virtual ~nsAString() { } };
#endif
class nsISizeOfHandler;
#define nsString2 nsString
#define nsAutoString2 nsAutoString
class NS_COM nsString :
public nsAFlatString,
public nsStr {
protected:
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const;
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
virtual const PRUnichar* get() const;
public:
/**
* Default constructor.
*/
nsString();
/**
* This is our copy constructor
* @param reference to another nsString
*/
nsString(const nsString& aString);
explicit nsString(const nsAString&);
explicit nsString(const PRUnichar*);
nsString(const PRUnichar*, PRInt32);
/**
* Destructor
*
*/
virtual ~nsString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string length
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**
* Determine whether or not the characters in this
* string are in store as 1 or 2 byte (unicode) strings.
*
* @return TRUE if ordered.
*/
PRBool IsUnicode(void) const {
PRBool result=PRBool(mCharSize==eTwoByte);
return result;
}
/**********************************************************************
Getters/Setters...
*********************************************************************/
/**
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
*/
const char* GetBuffer(void) const;
/**
* Set nth character.
*/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars( const char* aSet );
void StripChar( PRUnichar aChar, PRInt32 anOffset=0 );
void StripChar( char aChar, PRInt32 anOffset=0 ) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
void StripChar( PRInt32 anInt, PRInt32 anOffset=0 ) { StripChar((PRUnichar)anInt,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar( PRUnichar anOldChar, PRUnichar aNewChar );
void ReplaceChar( const char* aSet, PRUnichar aNewChar );
void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue );
void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue );
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsString is a clone of this string.
*
*/
nsString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates an UTF8 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new null-terminated UTF8 string
*/
char* ToNewUTF8String() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
* @return this
*/
nsString& operator=( const nsString& aString ) { Assign(aString); return *this; }
nsString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
//nsString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(char);
void AssignWithConversion(const char*);
void AssignWithConversion(const char*, PRInt32);
void AssignWithConversion(const nsAFlatCString& aCString)
{
AssignWithConversion(aCString.get(), aCString.Length());
}
void AssignWithConversion(const nsAFlatCString& aCString, PRInt32 aCount)
{
AssignWithConversion(aCString.get(), aCount);
}
/*
* Appends n characters from given string to this,
* This version computes the length of your given string
*
* @param aString is the source to be appended to this
* @return number of chars copied
*/
void AppendInt(PRInt32, PRInt32=10); //radix=8,10 or 16
void AppendFloat(double);
void AppendWithConversion(const char*, PRInt32=-1);
void AppendWithConversion(char);
void AppendWithConversion(const nsAFlatCString& aCString)
{
AppendWithConversion(aCString.get(), aCString.Length());
}
void AppendWithConversion(const nsAFlatCString& aCString, PRInt32 aCount)
{
AppendWithConversion(aCString.get(), aCount);
}
virtual void do_AppendFromElement( PRUnichar );
//void InsertWithConversion(char);
void InsertWithConversion(const char*, PRUint32, PRInt32=-1);
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where in this strig to start searching (counting from left)
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRInt32
CompareWithConversion(const nsXPIDLString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return CompareWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRBool
EqualsWithConversion(const nsXPIDLString &aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return EqualsWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsAtom(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
PRBool EqualsIgnoreCase(const nsString& aString) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
/**
* Determine if given buffer is plain ascii
*
* @param aBuffer -- if null, then we test *this, otherwise we test given buffer
* @return TRUE if is all ascii chars or if strlen==0
*/
PRBool IsASCII(const PRUnichar* aBuffer=0);
void DebugDump(void) const;
/**
* Determine if given char is a valid space character
*
* @param aChar is character to be tested
* @return TRUE if is valid space char
*/
static PRBool IsSpace(PRUnichar ch);
/**
* Determine if given char in valid alpha range
*
* @param aChar is character to be tested
* @return TRUE if in alpha range
*/
static PRBool IsAlpha(PRUnichar ch);
/**
* Determine if given char is valid digit
*
* @param aChar is character to be tested
* @return TRUE if char is a valid digit
*/
static PRBool IsDigit(PRUnichar ch);
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( char );
void AssignWithConversion( PRUnichar );
void AssignWithConversion( const PRUnichar*, PRInt32=-1 );
void AppendWithConversion( PRUnichar );
void AppendWithConversion( const PRUnichar*, PRInt32=-1 );
void InsertWithConversion( const PRUnichar*, PRUint32, PRInt32=-1 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsString, PRUnichar)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsString, PRUnichar)
extern NS_COM int fputs(const nsString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsAutoString : public nsString {
public:
virtual ~nsAutoString();
nsAutoString();
nsAutoString(const nsAutoString& aString);
explicit nsAutoString(const nsAString& aString);
explicit nsAutoString(const nsString& aString);
explicit nsAutoString(const PRUnichar* aString);
nsAutoString(const PRUnichar* aString,PRInt32 aLength);
explicit nsAutoString(PRUnichar aChar);
explicit nsAutoString(const CBufDescriptor& aBuffer);
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
public:
nsAutoString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
// nsAutoString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsAutoString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsAutoString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize<<eTwoByte];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsAutoString, PRUnichar)
class NS_COM NS_ConvertASCIItoUCS2
: public nsAutoString
/*
...
*/
{
public:
explicit
NS_ConvertASCIItoUCS2( const nsACString& aCString );
explicit
NS_ConvertASCIItoUCS2( const nsAFlatCString& aCString )
{
Init( aCString.get(), aCString.Length() );
}
explicit
NS_ConvertASCIItoUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertASCIItoUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertASCIItoUCS2( char );
#if 0
operator const nsDependentString() const
{
return nsDependentString(mUStr, mLength);
}
#endif
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertASCIItoUCS2( PRUnichar );
};
class NS_COM NS_ConvertUTF8toUCS2
: public nsAutoString
{
public:
explicit
NS_ConvertUTF8toUCS2( const nsACString& aCString );
explicit
NS_ConvertUTF8toUCS2( const nsAFlatCString& aCString )
{
Init( aCString.get(), aCString.Length() );
}
explicit
NS_ConvertUTF8toUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertUTF8toUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertUTF8toUCS2( char aChar )
{
Init( &aChar, 1 );
}
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
NS_ConvertUTF8toUCS2( PRUnichar );
};
#endif

View File

@@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDebug.h"
#include "nsMemory.h"
#include "nsXPIDLString.h"
#include "plstr.h"
// If the allocator changes, fix it here.
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsMemory::Alloc((__len) * sizeof(PRUnichar)))
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsMemory::Alloc((__len) * sizeof(char)))
#define XPIDL_FREE(__ptr) (nsMemory::Free(__ptr))
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
nsXPIDLString::~nsXPIDLString()
{
if (mBuf)
XPIDL_FREE(mBuf);
}
PRUnichar**
nsXPIDLString::StartAssignmentByValue()
{
if (mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
return &mBuf;
}
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
nsXPIDLCString::~nsXPIDLCString()
{
if (mBuf)
XPIDL_FREE(mBuf);
}
char**
nsXPIDLCString::StartAssignmentByValue()
{
if (mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
return &mBuf;
}

View File

@@ -1,323 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsXPIDLString.h --- an `|auto_ptr|' for character buffers, this functionality will be replaced
by the new shared-buffer string (see bug #53065)
*/
#ifndef nsXPIDLString_h__
#define nsXPIDLString_h__
/*
A set of string wrapper classes that ease transition to use of XPIDL
interfaces. nsXPIDLString and nsXPIDLCString are to XPIDL `wstring'
and `string' out params as nsCOMPtr is to generic XPCOM interface
pointers. They help you deal with object ownership.
Consider the following interface:
interface nsIFoo {
attribute string Bar;
};
This will generate the following C++ header file:
class nsIFoo {
NS_IMETHOD SetBar(const PRUnichar* aValue);
NS_IMETHOD GetBar(PRUnichar* *aValue);
};
The GetBar() method will allocate a copy of the nsIFoo object's
"bar" attribute, and leave you to deal with freeing it:
nsIFoo* aFoo; // assume we get this somehow
PRUnichar* bar;
aFoo->GetFoo(&bar);
// Use bar here...
printf("bar is %s!\n", bar);
nsMemory::Free(bar);
This makes your life harder, because you need to convolute your code
to ensure that you don't leak `bar'.
Enter nsXPIDLString, which manages the ownership of the allocated
string, and automatically destroys it when the nsXPIDLString goes
out of scope:
nsIFoo* aFoo;
nsXPIDLString bar;
aFoo->GetFoo( getter_Copies(bar) );
// Use bar here...
printf("bar is %s!\n", (const char*) bar);
// no need to remember to nsMemory::Free().
Like nsCOMPtr, nsXPIDLString uses some syntactic sugar to make it
painfully clear exactly what the code expects. You need to wrap an
nsXPIDLString object with `getter_Copies()'
before passing it to a getter: these tell the
nsXPIDLString how ownership is being handled.
In the case of `getter_Copies()', the callee is allocating a copy
(which is usually the case). In the case where the
callee is returning a const reference to `the real deal' (this can
be done using the [shared] attribute in XPIDL) you can just use
a |const char*|.
*/
#include "nscore.h"
#include "nsCom.h"
#include "prtypes.h"
#ifndef __PRUNICHAR__
#define __PRUNICHAR__
typedef PRUint16 PRUnichar;
#endif /* __PRUNICHAR__ */
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
//
// A wrapper for Unicode strings. With the |getter_Copies()|
// helper function, this can be used instead of
// the "naked" |PRUnichar*| interface for |wstring| parameters in
// XPIDL interfaces.
//
class NS_COM nsXPIDLString {
private:
PRUnichar* mBuf;
PRUnichar** StartAssignmentByValue();
public:
/**
* Construct a new, uninitialized wrapper for a Unicode string.
*/
nsXPIDLString() : mBuf(0) {}
~nsXPIDLString();
/**
* Return a reference to the immutable Unicode string.
*/
operator const PRUnichar*() const { return get(); }
/**
* Return a reference to the immutable Unicode string.
*/
const PRUnichar* get() const { return mBuf; }
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLString& mXPIDLString;
public:
GetterCopies(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator PRUnichar**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLString& aXPIDLString);
};
friend class GetterCopies;
inline void Adopt( PRUnichar* );
private:
// not to be implemented
nsXPIDLString(nsXPIDLString& /* aXPIDLString */) {}
void operator=(nsXPIDLString& /* aXPIDLString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive an |out| value.
*/
inline nsXPIDLString::GetterCopies
getter_Copies(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterCopies(aXPIDLString);
}
inline
void
nsXPIDLString::Adopt( PRUnichar* aNewValue )
{
*StartAssignmentByValue() = aNewValue;
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
{
return lhs == rhs.get();
}
inline
PRBool
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
{
return lhs.get() == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLString& rhs)
{
return NS_REINTERPRET_CAST(PRUnichar*, lhs) == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, int rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == NS_REINTERPRET_CAST(PRUnichar*, rhs);
}
#endif
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
//
// A wrapper for Unicode strings. With the |getter_Copies()|
// helper function, this can be used instead of
// the "naked" |char*| interface for |string| parameters in XPIDL
// interfaces.
//
class NS_COM nsXPIDLCString {
private:
char* mBuf;
char** StartAssignmentByValue();
public:
/**
* Construct a new, uninitialized wrapper for a single-byte string.
*/
nsXPIDLCString() : mBuf(0) {}
~nsXPIDLCString();
/**
* Return a reference to the immutable single-byte string.
*/
operator const char*() const { return get(); }
/**
* Return a reference to the immutable single-byte string.
*/
const char* get() const { return mBuf; }
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterCopies(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator char**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLCString& aXPIDLString);
};
friend class GetterCopies;
inline void Adopt( char* );
private:
// not to be implemented
nsXPIDLCString(nsXPIDLCString& /* aXPIDLString */) {}
void operator=(nsXPIDLCString& /* aXPIDLCString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive an |out| value.
*/
inline nsXPIDLCString::GetterCopies
getter_Copies(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterCopies(aXPIDLString);
}
inline
void
nsXPIDLCString::Adopt( char* aNewValue )
{
*StartAssignmentByValue() = aNewValue;
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const char* lhs, const nsXPIDLCString& rhs)
{
return lhs == rhs.get();
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, const char* rhs)
{
return lhs.get() == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLCString& rhs)
{
return NS_REINTERPRET_CAST(char*, lhs) == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, int rhs)
{
return NS_STATIC_CAST(const char*, lhs) == NS_REINTERPRET_CAST(char*, rhs);
}
#endif
#endif // nsXPIDLString_h__

View File

@@ -1,52 +0,0 @@
#
# 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)
#
nsAFlatString.h
nsAlgorithm.h
nsAPromiseString.h
nsAReadableString.h
nsAString.h
nsAStringGenerator.h
nsAWritableString.h
nsBufferHandle.h
nsBufferHandleUtils.h
nsCharTraits.h
nsDependentConcatenation.h
nsDependentString.h
nsDependentSubstring.h
nsFragmentedString.h
nsLiteralString.h
nsPrintfCString.h
nsPrivateSharableString.h
nsPromiseFlatString.h
nsReadableUtils.h
nsSharableString.h
nsSharedBufferList.h
nsSlidingString.h
nsStringDefines.h
nsStringFragment.h
nsStringFwd.h
nsStringIterator.h
nsStringIteratorUtils.h
nsStringTraits.h
nsXPIDLString.h

View File

@@ -1,67 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAStringGenerator.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsDependentConcatenation.h \
nsDependentString.h \
nsDependentSubstring.h \
nsFragmentedString.h \
nsLiteralString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseFlatString.h \
nsReadableUtils.h \
nsSharableString.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringDefines.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
nsXPIDLString.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,59 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAStringGenerator.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsDependentConcatenation.h \
nsDependentString.h \
nsDependentSubstring.h \
nsFragmentedString.h \
nsLiteralString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseFlatString.h \
nsReadableUtils.h \
nsSharableString.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringDefines.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
nsXPIDLString.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,85 +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)
*/
/* nsAFlatString.h --- */
#ifndef nsAFlatString_h___
#define nsAFlatString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
class NS_COM nsAFlatString
: public nsAString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsString| is really dead
virtual const PRUnichar* get() const;
PRUnichar operator[]( PRUint32 i ) const { return get()[ i ]; }
PRUnichar CharAt( PRUint32 ) const;
virtual PRUint32 Length() const;
// protected: // can't hide these (yet), since I call them from forwarding routines in |nsPromiseFlatString|
public:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
};
class NS_COM nsAFlatCString
: public nsACString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsCString| is really dead
virtual const char* get() const;
char operator[]( PRUint32 i ) const { return get()[ i ]; }
char CharAt( PRUint32 ) const;
virtual PRUint32 Length() const;
// protected: // can't hide these (yet), since I call them from forwarding routines in |nsPromiseFlatCString|
public:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
};
inline
PRUnichar
nsAFlatString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
inline
char
nsAFlatCString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
#endif /* !defined(nsAFlatString_h___) */

View File

@@ -1,38 +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)
*/
/* nsAPromiseString.h --- abstract base class for strings don't actually own their own characters, but proxy data from other strings */
#ifndef nsAPromiseString_h___
#define nsAPromiseString_h___
/**
* Don't |#include| this file yourself. You will get it automatically if you need it.
*
* Why is it a separate file? To make it easier to find the classes in your local tree.
*/
class NS_COM nsAPromiseString : public nsAString { };
class NS_COM nsAPromiseCString : public nsACString { };
#endif /* !defined(nsAPromiseString_h___) */

View File

@@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAReadableString.h --- a compatibility header for clients still using the names |nsAReadable[C]String| et al */
#ifndef nsAReadableString_h___
#define nsAReadableString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
typedef const nsAString nsAReadableString;
typedef const nsACString nsAReadableCString;
#ifndef nsLiteralString_h___
#include "nsLiteralString.h"
#endif
#ifndef nDependentSubstring_h___
#include "nsDependentSubstring.h"
#endif
#ifndef nsPromiseFlatString_h___
#include "nsPromiseFlatString.h"
#endif
#ifdef NEED_CPP_TEMPLATE_CAST_TO_BASE
#define NS_READABLE_CAST(CharT, expr) (NS_STATIC_CAST(const nsStringTraits<CharT>::abstract_string_type&, (expr)))
#else
#define NS_READABLE_CAST(CharT, expr) (expr)
#endif
#endif // !defined(nsAReadableString_h___)

View File

@@ -1,813 +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)
*/
#ifndef nsAString_h___
#define nsAString_h___
#ifndef nsStringFwd_h___
#include "nsStringFwd.h"
#endif
#ifndef nsPrivateSharableString_h___
#include "nsPrivateSharableString.h"
#endif
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
#endif
#ifndef nsStringIterator_h___
#include "nsStringIterator.h"
#endif
/**
*
*/
class NS_COM nsAString
: public nsPrivateSharableString
{
public:
typedef nsAString self_type;
typedef nsAPromiseString promise_type;
typedef PRUnichar char_type;
typedef char incompatible_char_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
// nsAString(); // auto-generated default constructor OK (we're abstract anyway)
// nsAString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsAString() { } // ...yes, I expect to be sub-classed
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, index_type aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool IsDependentOn( const self_type& aString ) const { return &aString == this; }
};
class NS_COM nsACString
: public nsPrivateSharableCString
{
public:
typedef nsACString self_type;
typedef nsAPromiseCString promise_type;
typedef char char_type;
typedef PRUnichar incompatible_char_type;
typedef nsReadingIterator<char_type> const_iterator;
typedef nsWritingIterator<char_type> iterator;
typedef PRUint32 size_type;
typedef PRUint32 index_type;
// nsACString(); // auto-generated default constructor OK (we're abstract anyway)
// nsACString( const self_type& ); // auto-generated copy-constructor OK (again, only because we're abstract)
virtual ~nsACString() { } // ...yes, I expect to be sub-classed
inline const_iterator& BeginReading( const_iterator& ) const;
inline const_iterator& EndReading( const_iterator& ) const;
inline iterator& BeginWriting( iterator& );
inline iterator& EndWriting( iterator& );
virtual size_type Length() const = 0;
PRBool IsEmpty() const { return Length() == 0; }
inline PRBool Equals( const self_type& ) const;
PRBool Equals( const char_type* ) const;
/**
* |CharAt|, |operator[]|, |First()|, and |Last()| are not guaranteed to be constant-time operations.
* These signatures should be pushed down into interfaces that guarantee flat allocation.
* Clients at _this_ level should always use iterators.
*/
char_type First() const;
char_type Last() const;
size_type CountChar( char_type ) const;
/*
|Left|, |Mid|, and |Right| are annoying signatures that seem better almost
any _other_ way than they are now. Consider these alternatives
aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
Left(aReadable, 17, aWritable); // ...a global function that does the assignment
as opposed to the current signature
aReadable.Left(aWritable, 17); // ...a member function that does the assignment
or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
aWritable = Substring(aReadable, 0, 17);
*/
size_type Left( self_type&, size_type ) const;
size_type Mid( self_type&, PRUint32, PRUint32 ) const;
size_type Right( self_type&, size_type ) const;
// Find( ... ) const;
PRInt32 FindChar( char_type, PRUint32 aOffset = 0 ) const;
// FindCharInSet( ... ) const;
// RFind( ... ) const;
// RFindChar( ... ) const;
// RFindCharInSet( ... ) const;
/**
* |SetCapacity| is not required to do anything; however, it can be used
* as a hint to the implementation to reduce allocations.
* |SetCapacity(0)| is a suggestion to discard all associated storage.
*/
virtual void SetCapacity( size_type ) { }
/**
* |SetLength| is used in two ways:
* 1) to |Cut| a suffix of the string;
* 2) to prepare to |Append| or move characters around.
*
* External callers are not allowed to use |SetLength| is this latter capacity.
* Should this really be a public operation?
* Additionally, your implementation of |SetLength| need not satisfy (2) if and only if you
* override the |do_...| routines to not need this facility.
*
* This distinction makes me think the two different uses should be split into
* two distinct functions.
*/
virtual void SetLength( size_type ) { }
void
Truncate( size_type aNewLength=0 )
{
NS_ASSERTION(aNewLength<=this->Length(), "Can't use |Truncate()| to make a string longer.");
if ( aNewLength < this->Length() )
SetLength(aNewLength);
}
// PRBool SetCharAt( char_type, index_type ) = 0;
// void ToLowerCase();
// void ToUpperCase();
// void StripChars( const char_type* aSet );
// void StripChar( ... );
// void StripWhitespace();
// void ReplaceChar( ... );
// void ReplaceSubstring( ... );
// void Trim( ... );
// void CompressSet( ... );
// void CompressWhitespace( ... );
//
// |Assign()|, |operator=()|
//
void Assign( const self_type& aReadable ) { AssignFromReadable(aReadable); }
inline void Assign( const promise_type& aReadable );
void Assign( const char_type* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
void Assign( const char_type* aPtr, size_type aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
void Assign( char_type aChar ) { do_AssignFromElement(aChar); }
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
self_type& operator=( const self_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const promise_type& aReadable ) { Assign(aReadable); return *this; }
self_type& operator=( const char_type* aPtr ) { Assign(aPtr); return *this; }
self_type& operator=( char_type aChar ) { Assign(aChar); return *this; }
//
// |Append()|, |operator+=()|
//
void Append( const self_type& aReadable ) { AppendFromReadable(aReadable); }
inline void Append( const promise_type& aReadable );
void Append( const char_type* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
void Append( const char_type* aPtr, size_type aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
void Append( char_type aChar ) { do_AppendFromElement(aChar); }
self_type& operator+=( const self_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const promise_type& aReadable ) { Append(aReadable); return *this; }
self_type& operator+=( const char_type* aPtr ) { Append(aPtr); return *this; }
self_type& operator+=( char_type aChar ) { Append(aChar); return *this; }
/**
* The following index based routines need to be recast with iterators.
*/
//
// |Insert()|
// Note: I would really like to move the |atPosition| parameter to the front of the argument list
//
void Insert( const self_type& aReadable, index_type atPosition ) { InsertFromReadable(aReadable, atPosition); }
inline void Insert( const promise_type& aReadable, index_type atPosition );
void Insert( const char_type* aPtr, index_type atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
void Insert( const char_type* aPtr, index_type atPosition, size_type aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
void Insert( char_type aChar, index_type atPosition ) { do_InsertFromElement(aChar, atPosition); }
virtual void Cut( index_type cutStart, size_type cutLength );
void Replace( index_type cutStart, size_type cutLength, const self_type& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
// void Replace( index_type cutStart, size_type cutLength, const promise_type& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
private:
// NOT TO BE IMPLEMENTED
index_type CountChar( incompatible_char_type ) const;
void operator= ( incompatible_char_type );
void Assign ( incompatible_char_type );
void operator+= ( incompatible_char_type );
void Append ( incompatible_char_type );
void Insert ( incompatible_char_type, index_type );
protected:
void AssignFromReadable( const self_type& );
void AssignFromPromise( const self_type& );
virtual void do_AssignFromReadable( const self_type& );
virtual void do_AssignFromElementPtr( const char_type* );
virtual void do_AssignFromElementPtrLength( const char_type*, size_type );
virtual void do_AssignFromElement( char_type );
void AppendFromReadable( const self_type& );
void AppendFromPromise( const self_type& );
virtual void do_AppendFromReadable( const self_type& );
virtual void do_AppendFromElementPtr( const char_type* );
virtual void do_AppendFromElementPtrLength( const char_type*, size_type );
virtual void do_AppendFromElement( char_type );
void InsertFromReadable( const self_type&, index_type );
void InsertFromPromise( const self_type&, index_type );
virtual void do_InsertFromReadable( const self_type&, index_type );
virtual void do_InsertFromElementPtr( const char_type*, index_type );
virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type );
virtual void do_InsertFromElement( char_type, index_type );
void ReplaceFromReadable( index_type, size_type, const self_type& );
void ReplaceFromPromise( index_type, size_type, const self_type& );
virtual void do_ReplaceFromReadable( index_type, size_type, const self_type& );
// protected:
public:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
virtual PRBool IsDependentOn( const self_type& aString ) const { return &aString == this; }
};
#include "nsAPromiseString.h"
inline
void
nsAString::Assign( const nsAPromiseString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsAString::Append( const nsAPromiseString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsAString::Insert( const nsAPromiseString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
inline
void
nsACString::Assign( const nsAPromiseCString& aReadable )
{
AssignFromPromise(aReadable);
}
inline
void
nsACString::Append( const nsAPromiseCString& aReadable )
{
AppendFromPromise(aReadable);
}
inline
void
nsACString::Insert( const nsAPromiseCString& aReadable, index_type atPosition )
{
InsertFromPromise(aReadable, atPosition);
}
/**
* Note: measure -- should the |Begin...| and |End...| be |inline|?
*/
inline
nsAString::const_iterator&
nsAString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::const_iterator&
nsAString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsAString::iterator&
nsAString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsAString::iterator&
nsAString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
class NS_COM nsStringComparator
{
public:
virtual int operator()( const PRUnichar*, const PRUnichar*, PRUint32 aLength ) const = 0;
};
class NS_COM nsDefaultStringComparator
: public nsStringComparator
{
public:
virtual int operator()( const PRUnichar*, const PRUnichar*, PRUint32 aLength ) const;
};
class NS_COM nsCaseInsensitiveStringComparator
: public nsStringComparator
{
public:
virtual int operator()( const PRUnichar*, const PRUnichar*, PRUint32 aLength ) const;
};
NS_COM int Compare( const nsAString& lhs, const nsAString& rhs, const nsStringComparator& = nsDefaultStringComparator() );
inline
PRBool
nsAString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsAString& lhs, const nsAString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsAString& lhs, const nsAString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsAString& lhs, const nsAString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsAString::size_type
nsAString::Left( nsAString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
/**
*
*/
inline
nsACString::const_iterator&
nsACString::BeginReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::const_iterator&
nsACString::EndReading( const_iterator& aResult ) const
{
aResult.mOwningString = this;
GetReadableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
inline
nsACString::iterator&
nsACString::BeginWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kFirstFragment);
aResult.mPosition = aResult.mFragment.mStart;
aResult.normalize_forward();
return aResult;
}
inline
nsACString::iterator&
nsACString::EndWriting( iterator& aResult )
{
aResult.mOwningString = this;
GetWritableFragment(aResult.mFragment, kLastFragment);
aResult.mPosition = aResult.mFragment.mEnd;
// must not |normalize_backward| as that would likely invalidate tests like |while ( first != last )|
return aResult;
}
class NS_COM nsCStringComparator
{
public:
virtual int operator()( const char*, const char*, PRUint32 aLength ) const = 0;
};
class NS_COM nsDefaultCStringComparator
: public nsCStringComparator
{
public:
virtual int operator()( const char*, const char*, PRUint32 aLength ) const;
};
class NS_COM nsCaseInsensitiveCStringComparator
: public nsCStringComparator
{
public:
virtual int operator()( const char*, const char*, PRUint32 aLength ) const;
};
NS_COM int Compare( const nsACString& lhs, const nsACString& rhs, const nsCStringComparator& = nsDefaultCStringComparator() );
inline
PRBool
nsACString::Equals( const self_type& rhs ) const
{
return Length()==rhs.Length() && Compare(*this, rhs)==0;
}
inline
PRBool
operator!=( const nsACString& lhs, const nsACString& rhs )
{
return !lhs.Equals(rhs);
}
inline
PRBool
operator< ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)< 0;
}
inline
PRBool
operator<=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)<=0;
}
inline
PRBool
operator==( const nsACString& lhs, const nsACString& rhs )
{
return lhs.Equals(rhs);
}
inline
PRBool
operator>=( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)>=0;
}
inline
PRBool
operator> ( const nsACString& lhs, const nsACString& rhs )
{
return Compare(lhs, rhs)> 0;
}
inline
nsACString::size_type
nsACString::Left( nsACString& aResult, size_type aLengthToCopy ) const
{
return Mid(aResult, 0, aLengthToCopy);
}
// Once you've got strings, you shouldn't need to do anything else to have concatenation
#ifndef nsDependentConcatenation_h___
#include "nsDependentConcatenation.h"
#endif
#endif // !defined(nsAString_h___)

View File

@@ -1,64 +0,0 @@
/*
* 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)
*/
/* nsAStringGenerator.h --- generators produce strings into a callers buffer, avoiding temporaries */
#ifndef nsAStringGenerator_h___
#define nsAStringGenerator_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
#include "nscore.h"
// for |PRUnichar|
#include "prtypes.h"
// for |PRBool|, |PRUint32|
class nsAString;
class nsACString;
class nsAStringGenerator
{
public:
virtual ~nsAStringGenerator() { }
virtual PRUnichar* operator()( PRUnichar* aDestBuffer ) const = 0;
virtual PRUint32 Length() const = 0;
virtual PRUint32 MaxLength() const = 0;
virtual PRBool IsDependentOn( const nsAString& ) const = 0;
};
class nsACStringGenerator
{
public:
virtual ~nsACStringGenerator() { }
virtual char* operator()( char* aDestBuffer ) const = 0;
virtual PRUint32 Length() const = 0;
virtual PRUint32 MaxLength() const = 0;
virtual PRBool IsDependentOn( const nsACString& ) const = 0;
};
#endif // !defined(nsAStringGenerator_h___)

View File

@@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
/* nsAWritableString.h --- a compatibility header for clients still using the names |nsAWritable[C]String| */
#ifndef nsAWritableString_h___
#define nsAWritableString_h___
#ifndef nsAReadableString_h___
#include "nsAReadableString.h"
#endif
typedef nsAString nsAWritableString;
typedef nsACString nsAWritableCString;
#endif // !defined(nsAWritableString_h___)

View File

@@ -1,112 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsAlgorithm_h___
#define nsAlgorithm_h___
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
// for |nsCharSourceTraits|, |nsCharSinkTraits|
#endif
#ifndef prtypes_h___
#include "prtypes.h"
// for |PRUint32|...
#endif
template <class T>
inline
const T&
NS_MIN( const T& a, const T& b )
{
return b < a ? b : a;
}
template <class T>
inline
const T&
NS_MAX( const T& a, const T& b )
{
return a > b ? a : b;
}
template <class InputIterator, class T>
inline
PRUint32
NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
{
PRUint32 result = 0;
for ( ; first != last; ++first )
if ( *first == value )
++result;
return result;
}
template <class InputIterator, class OutputIterator>
inline
OutputIterator&
copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
{
typedef nsCharSourceTraits<InputIterator> source_traits;
typedef nsCharSinkTraits<OutputIterator> sink_traits;
while ( first != last )
{
PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
source_traits::advance(first, count_copied);
}
return result;
}
template <class InputIterator, class OutputIterator>
OutputIterator&
copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
{
while ( first != last )
{
last.normalize_backward();
result.normalize_backward();
PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
if ( first.fragment().mStart == last.fragment().mStart )
lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
#ifdef _MSC_VER
// XXX Visual C++ can't stomach 'typename' where it rightfully should
nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#else
nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
#endif
last.advance( -PRInt32(lengthToCopy) );
result.advance( -PRInt32(lengthToCopy) );
}
return result;
}
#endif // !defined(nsAlgorithm_h___)

View File

@@ -1,368 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
/* nsBufferHandle.h --- the collection of classes that describe the atomic hunks of strings */
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nscore.h"
// for |PRUnichar|, |NS_REINTERPRET_CAST|
#ifdef XP_WIN
// VC++ erroneously warns about incompatible linkage in these templates
// It's a lie, and it's bothersome. This |#pragma| quiets the warning.
#pragma warning( disable: 4251 )
#endif
/**
The classes in this file are collectively called `buffer handles'.
All buffer handles begin with a pointer-tuple that delimits the useful content of a
hunk of string. A buffer handle that points to a sharable hunk of string data
additionally has a field which multiplexes some flags and a reference count.
ns[Const]BufferHandle nsSharedBufferHandle mFlexBufferHandle
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mDataStart | | mDataStart | | mDataStart |
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mDataEnd | | mDataEnd | | mDataEnd |
+-----+-----+-----+-----+ +-----+-----+-----+-----+ +-----+-----+-----+-----+
| mFlags | | mFlags |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
. mAllocator . | mStorageStart |
......................... +-----+-----+-----+-----+
| mStorageEnd |
+-----+-----+-----+-----+
. mAllocator .
.........................
Given only a |ns[Const]BufferHandle|, there is no legal way to tell if it is sharable.
In all cases, the data might immediately follow the handle in the same allocated block.
From the |mFlags| field, you can tell exactly what configuration of a handle you
actually have.
*/
/**
*
*/
template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle() { }
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
CharT* mDataStart;
CharT* mDataEnd;
};
template <class CharT>
class nsConstBufferHandle
{
public:
nsConstBufferHandle() { }
nsConstBufferHandle( const CharT* aDataStart, const CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
void DataStart( const CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
const CharT* DataStart() const { return mDataStart; }
void DataEnd( const CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
const CharT* mDataStart;
const CharT* mDataEnd;
};
/**
* string allocator stuff needs to move to its own file
* also see http://bugzilla.mozilla.org/show_bug.cgi?id=70087
*/
template <class CharT>
class nsStringAllocator
{
public:
// more later
virtual void Deallocate( CharT* ) const = 0;
};
/**
* the following two routines must be provided by the client embedding strings
*/
NS_COM nsStringAllocator<char>& StringAllocator_char();
NS_COM nsStringAllocator<PRUnichar>& StringAllocator_wchar_t();
/**
* this traits class lets templated clients pick the appropriate non-template global allocator
*/
template <class T>
struct nsStringAllocatorTraits
{
};
NS_SPECIALIZE_TEMPLATE
struct nsStringAllocatorTraits<char>
{
static nsStringAllocator<char>& global_string_allocator() { return StringAllocator_char(); }
};
NS_SPECIALIZE_TEMPLATE
struct nsStringAllocatorTraits<PRUnichar>
{
static nsStringAllocator<PRUnichar>& global_string_allocator() { return StringAllocator_wchar_t(); }
};
// end of string allocator stuff that needs to move
/**
*
*/
template <class CharT>
class nsSharedBufferHandle
: public nsBufferHandle<CharT>
{
protected:
enum
{
kIsShared = 0x08000000, // one reason _not_ to set this is for a stack based handle that wants to express `NULL'-ness et al
kIsSingleAllocationWithBuffer = 0x04000000, // handle and buffer are one piece, no separate deallocation is possible for the buffer
kIsStorageDefinedSeparately = 0x02000000, // i.e., we're using the ``flex'' structure defined below
kIsUserAllocator = 0x01000000, // can't |delete|, call a hook instead
// the following flags are opaque to the string library itself
kIsNULL = 0x80000000, // the most common request of external clients is a scheme by which they can express `NULL'-ness
kImplementationFlagsMask = 0xF0000000, // 4 bits for use by site-implementations, e.g., for `NULL'-ness
kFlagsMask = 0xFF000000,
kRefCountMask = 0x00FFFFFF
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
{
mFlags = kIsShared;
}
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT*, CharT*, PRBool isSingleAllocation )
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
{
mFlags = kIsShared;
if ( isSingleAllocation )
mFlags |= kIsSingleAllocationWithBuffer;
}
~nsSharedBufferHandle();
void
AcquireReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
mutable_this->set_refcount( get_refcount()+1 );
}
void
ReleaseReference() const
{
nsSharedBufferHandle<CharT>* mutable_this = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, this);
if ( !mutable_this->set_refcount( get_refcount()-1 ) )
delete mutable_this;
// hmm, what if |kIsUserAllocator| and |kIsSingleAllocationWithBuffer|?
}
PRBool
IsReferenced() const
{
return get_refcount() != 0;
}
PRUint32
GetImplementationFlags() const
{
return mFlags & kImplementationFlagsMask;
}
void
SetImplementationFlags( PRUint32 aNewFlags )
{
mFlags = (mFlags & ~kImplementationFlagsMask) | (aNewFlags & kImplementationFlagsMask);
}
protected:
PRUint32 mFlags;
PRUint32
get_refcount() const
{
return mFlags & kRefCountMask;
}
PRUint32
set_refcount( PRUint32 aNewRefCount )
{
NS_ASSERTION(aNewRefCount <= kRefCountMask, "aNewRefCount <= kRefCountMask");
mFlags = (mFlags & kFlagsMask) | aNewRefCount;
return aNewRefCount;
}
nsStringAllocator<CharT>& get_allocator() const;
};
template <class CharT>
class nsFlexBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsFlexBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
this->mFlags |= this->kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
class nsSharedBufferHandleWithAllocator
: public nsSharedBufferHandle<CharT>
{
public:
nsSharedBufferHandleWithAllocator( CharT* aDataStart, CharT* aDataEnd, nsStringAllocator<CharT>& aAllocator )
: nsSharedBufferHandle<CharT>(aDataStart, aDataEnd),
mAllocator(aAllocator)
{
this->mFlags |= this->kIsUserAllocator;
}
nsStringAllocator<CharT>& get_allocator() const { return mAllocator; }
protected:
nsStringAllocator<CharT>& mAllocator;
};
template <class CharT>
class nsFlexBufferHandleWithAllocator
: public nsFlexBufferHandle<CharT>
{
public:
nsFlexBufferHandleWithAllocator( CharT* aDataStart, CharT* aDataEnd,
CharT* aStorageStart, CharT* aStorageEnd,
nsStringAllocator<CharT>& aAllocator )
: nsFlexBufferHandle<CharT>(aDataStart, aDataEnd, aStorageStart, aStorageEnd),
mAllocator(aAllocator)
{
this->mFlags |= this->kIsUserAllocator;
}
nsStringAllocator<CharT>& get_allocator() const { return mAllocator; }
protected:
nsStringAllocator<CharT>& mAllocator;
};
template <class CharT>
nsStringAllocator<CharT>&
nsSharedBufferHandle<CharT>::get_allocator() const
// really don't want this to be |inline|
{
if ( mFlags & kIsUserAllocator )
{
if ( mFlags & kIsStorageDefinedSeparately )
return NS_REINTERPRET_CAST(const nsFlexBufferHandleWithAllocator<CharT>*, this)->get_allocator();
else
return NS_REINTERPRET_CAST(const nsSharedBufferHandleWithAllocator<CharT>*, this)->get_allocator();
}
return nsStringAllocatorTraits<CharT>::global_string_allocator();
}
template <class CharT>
nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
// really don't want this to be |inline|
{
NS_ASSERTION(!IsReferenced(), "!IsReferenced()");
if ( !(mFlags & kIsSingleAllocationWithBuffer) )
{
CharT* string_storage = this->mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_REINTERPRET_CAST(nsFlexBufferHandle<CharT>*, this)->StorageStart();
get_allocator().Deallocate(string_storage);
}
}
#endif // !defined(nsBufferHandle_h___)

View File

@@ -1,186 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsBufferHandleUtils_h___
#define nsBufferHandleUtils_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
#include <new.h>
// for placement |new|
template <class CharT>
class nsAutoBufferHandle
{
public:
nsAutoBufferHandle() : mHandle(0) { }
nsAutoBufferHandle( const nsAutoBufferHandle<CharT>& aOther )
: mHandle(aOther.get())
{
if ( mHandle )
mHandle->AcquireReference();
}
explicit
nsAutoBufferHandle( const nsSharedBufferHandle<CharT>* aHandle )
: mHandle( NS_CONST_CAST(nsSharedBufferHandle<CharT>*, aHandle) )
{
if ( mHandle )
mHandle->AcquireReference();
}
~nsAutoBufferHandle()
{
if ( mHandle )
mHandle->ReleaseReference();
}
nsAutoBufferHandle<CharT>&
operator=( const nsSharedBufferHandle<CharT>* rhs )
{
nsSharedBufferHandle<CharT>* old_handle = mHandle;
if ( (mHandle = NS_CONST_CAST(nsSharedBufferHandle<CharT>*, rhs)) )
mHandle->AcquireReference();
if ( old_handle )
old_handle->ReleaseReference();
return *this;
}
nsAutoBufferHandle<CharT>&
operator=( const nsAutoBufferHandle<CharT>& rhs )
{
return operator=(rhs.get());
}
nsSharedBufferHandle<CharT>*
get() const
{
return mHandle;
}
operator nsSharedBufferHandle<CharT>*() const
{
return get();
}
nsSharedBufferHandle<CharT>*
operator->() const
{
return get();
}
private:
nsSharedBufferHandle<CharT>* mHandle;
};
template <class HandleT, class CharT>
inline
size_t
NS_AlignedHandleSize( const HandleT*, const CharT* )
{
// figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part
return ((sizeof(HandleT) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
}
template <class HandleT, class CharT>
inline
const CharT*
NS_DataAfterHandle( const HandleT* aHandlePtr, const CharT* aDummyCharTPtr )
{
typedef const CharT* CharT_ptr;
return CharT_ptr(NS_STATIC_CAST(const unsigned char*, aHandlePtr) + NS_AlignedHandleSize(aHandlePtr, aDummyCharTPtr));
}
template <class HandleT, class CharT>
inline
CharT*
NS_DataAfterHandle( HandleT* aHandlePtr, const CharT* aDummyCharTPtr )
{
typedef CharT* CharT_ptr;
return CharT_ptr(NS_STATIC_CAST(unsigned char*, aHandlePtr) + NS_AlignedHandleSize(aHandlePtr, aDummyCharTPtr));
}
template <class HandleT, class StringT>
HandleT*
NS_AllocateContiguousHandleWithData( const HandleT* aDummyHandlePtr, PRUint32 aAdditionalCapacity, const StringT* aDataSource )
{
typedef typename StringT::char_type char_type;
typedef char_type* char_ptr;
// figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part
size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, char_ptr(0));
// figure out how many |char_type|s wee need to fit in the data part
size_t data_length = aDataSource? aDataSource->Length() : 0;
size_t buffer_length = data_length + aAdditionalCapacity;
// how many bytes is that (including a zero-terminator so we can claim to be flat)?
size_t buffer_size = buffer_length * sizeof(char_type);
HandleT* result = 0;
void* handle_ptr = ::operator new(handle_size + buffer_size);
if ( handle_ptr )
{
char_ptr data_start_ptr = char_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size);
char_ptr data_end_ptr = data_start_ptr + data_length;
char_ptr buffer_end_ptr = data_start_ptr + buffer_length;
char_ptr toBegin = data_start_ptr;
if ( data_length )
{
typename StringT::const_iterator fromBegin, fromEnd;
copy_string(aDataSource->BeginReading(fromBegin), aDataSource->EndReading(fromEnd), toBegin);
}
// and if the caller bothered asking for a buffer bigger than their string, we'll zero-terminate
if ( aAdditionalCapacity > 0 )
*toBegin = char_type(0);
result = new (handle_ptr) HandleT(data_start_ptr, data_end_ptr, data_start_ptr, buffer_end_ptr, PR_TRUE);
}
return result;
}
template <class HandleT, class StringT>
inline
HandleT*
NS_AllocateContiguousHandleWithData( const HandleT* aDummyHandlePtr, const StringT& aDataSource, PRUint32 aAdditionalCapacity )
{
return NS_AllocateContiguousHandleWithData(aDummyHandlePtr, aAdditionalCapacity, &aDataSource);
}
#endif // !defined(nsBufferHandleUtils_h___)

View File

@@ -1,709 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#ifndef nsCharTraits_h___
#define nsCharTraits_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
#include <ctype.h>
// for |EOF|, |WEOF|
#include <string.h>
// for |memcpy|, et al
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifndef nsStringIteratorUtils_h___
#include "nsStringIteratorUtils.h"
#endif
#ifdef HAVE_CPP_BOOL
typedef bool nsCharTraits_bool;
#else
typedef PRBool nsCharTraits_bool;
#endif
template <class CharT>
struct nsCharTraits
{
typedef CharT char_type;
typedef char incompatible_char_type;
static
void
assign( char_type& lhs, const char_type& rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char_type
to_char_type( const int_type& c )
{
return char_type(c);
}
static
int_type
to_int_type( const char_type& c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( const int_type& lhs, const int_type& rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( const char_type& lhs, const char_type& rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( const char_type& lhs, const char_type& rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char_type*
copy( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
while ( n-- )
assign(*s1++, *s2++);
return result;
}
static
char_type*
move( char_type* s1, const char_type* s2, size_t n )
{
char_type* result = s1;
if ( n )
{
if ( s2 > s1 )
copy(s1, s2, n);
else
{
s1 += n;
s2 += n;
while ( n-- )
assign(*--s1, *--s2);
}
}
return result;
}
static
char_type*
assign( char_type* s, size_t n, const char_type& c )
{
char_type* result = s;
while ( n-- )
assign(*s++, c);
return result;
}
static
int
compare( const char_type* s1, const char_type* s2, size_t n )
{
for ( ; n--; ++s1, ++s2 )
{
if ( lt(*s1, *s2) )
return -1;
if ( lt(*s2, *s1) )
return 1;
}
return 0;
}
static
size_t
length( const char_type* s )
{
size_t result = 0;
while ( !eq(*s++, CharT(0)) )
++result;
return result;
}
static
const char_type*
find( const char_type* s, size_t n, const char_type& c )
{
while ( n-- )
{
if ( eq(*s, c) )
return s;
++s;
}
return 0;
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int_type
not_eof( const int_type& c )
{
return eq_int_type(c, eof()) ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<char>
{
typedef char char_type;
typedef PRUnichar incompatible_char_type;
static
void
assign( char& lhs, char rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef int int_type;
static
char
to_char_type( int c )
{
return char(c);
}
static
int
to_int_type( char c )
{
return int( NS_STATIC_CAST(unsigned char, c) );
}
static
nsCharTraits_bool
eq_int_type( int lhs, int rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( char lhs, char rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( char lhs, char rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
char*
move( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memmove(s1, s2, n));
}
static
char*
copy( char* s1, const char* s2, size_t n )
{
return NS_STATIC_CAST(char*, memcpy(s1, s2, n));
}
static
char*
assign( char* s, size_t n, char c )
{
return NS_STATIC_CAST(char*, memset(s, to_int_type(c), n));
}
static
int
compare( const char* s1, const char* s2, size_t n )
{
return memcmp(s1, s2, n);
}
static
size_t
length( const char* s )
{
return strlen(s);
}
static
const char*
find( const char* s, size_t n, char c )
{
return NS_REINTERPRET_CAST(const char*, memchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return EOF;
}
static
int
not_eof( int c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#if 0
NS_SPECIALIZE_TEMPLATE
struct nsCharTraits<wchar_t>
{
typedef wchar_t char_type;
static
void
assign( wchar_t& lhs, wchar_t rhs )
{
lhs = rhs;
}
// integer representation of characters:
typedef wint_t int_type;
static
wchar_t
to_char_type( int_type c )
{
return wchar_t(c);
}
static
int_type
to_int_type( wchar_t c )
{
return int_type(c);
}
static
nsCharTraits_bool
eq_int_type( int_type lhs, int_type rhs )
{
return lhs == rhs;
}
// |char_type| comparisons:
static
nsCharTraits_bool
eq( wchar_t lhs, wchar_t rhs )
{
return lhs == rhs;
}
static
nsCharTraits_bool
lt( wchar_t lhs, wchar_t rhs )
{
return lhs < rhs;
}
// operations on s[n] arrays:
static
wchar_t*
move( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemmove(s1, s2, n));
}
static
wchar_t*
copy( wchar_t* s1, const wchar_t* s2, size_t n )
{
return NS_STATIC_CAST(wchar_t*, wmemcpy(s1, s2, n));
}
static
wchar_t*
assign( wchar_t* s, size_t n, wchar_t c )
{
return NS_STATIC_CAST(wchar_t*, wmemset(s, to_int_type(c), n));
}
static
int
compare( const wchar_t* s1, const wchar_t* s2, size_t n )
{
return wmemcmp(s1, s2, n);
}
static
size_t
length( const wchar_t* s )
{
return wcslen(s);
}
static
const wchar_t*
find( const wchar_t* s, size_t n, wchar_t c )
{
return NS_REINTERPRET_CAST(const wchar_t*, wmemchr(s, to_int_type(c), n));
}
#if 0
// I/O related:
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;
static
int_type
eof()
{
return WEOF;
}
static
int_type
not_eof( int_type c )
{
return c==eof() ? ~eof() : c;
}
// static state_type get_state( pos_type );
#endif
};
#endif
template <class InputIterator>
struct nsCharSourceTraits
{
typedef typename InputIterator::difference_type difference_type;
#if 0
static
PRUint32
distance( const InputIterator& first, const InputIterator& last )
{
// ...
}
#endif
static
PRUint32
readable_distance( const InputIterator& iter )
{
return iter.size_forward();
}
static
PRUint32
readable_distance( const InputIterator& first, const InputIterator& last )
{
return PRUint32(SameFragment(first, last) ? last.get()-first.get() : first.size_forward());
}
static
const typename InputIterator::value_type*
read( const InputIterator& iter )
{
return iter.get();
}
static
void
advance( InputIterator& s, difference_type n )
{
s.advance(n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSourceTraits<CharT*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( CharT* s )
{
return PRUint32(nsCharTraits<CharT>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( CharT* first, CharT* last )
{
return PRUint32(last-first);
}
static
const CharT*
read( CharT* s )
{
return s;
}
static
void
advance( CharT*& s, difference_type n )
{
s += n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const char*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const char* s )
{
return PRUint32(nsCharTraits<char>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const char* first, const char* last )
{
return PRUint32(last-first);
}
static
const char*
read( const char* s )
{
return s;
}
static
void
advance( const char*& s, difference_type n )
{
s += n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSourceTraits<const PRUnichar*>
{
typedef ptrdiff_t difference_type;
#if 0
static
PRUint32
distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
#endif
static
PRUint32
readable_distance( const PRUnichar* s )
{
return PRUint32(nsCharTraits<PRUnichar>::length(s));
// return numeric_limits<PRUint32>::max();
}
static
PRUint32
readable_distance( const PRUnichar* first, const PRUnichar* last )
{
return PRUint32(last-first);
}
static
const PRUnichar*
read( const PRUnichar* s )
{
return s;
}
static
void
advance( const PRUnichar*& s, difference_type n )
{
s += n;
}
};
#endif
template <class OutputIterator>
struct nsCharSinkTraits
{
static
PRUint32
write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
{
return iter.write(s, n);
}
};
#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
template <class CharT>
struct nsCharSinkTraits<CharT*>
{
static
PRUint32
write( CharT*& iter, const CharT* s, PRUint32 n )
{
nsCharTraits<CharT>::move(iter, s, n);
iter += n;
return n;
}
};
#else
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<char*>
{
static
PRUint32
write( char*& iter, const char* s, PRUint32 n )
{
nsCharTraits<char>::move(iter, s, n);
iter += n;
return n;
}
};
NS_SPECIALIZE_TEMPLATE
struct nsCharSinkTraits<PRUnichar*>
{
static
PRUint32
write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
{
nsCharTraits<PRUnichar>::move(iter, s, n);
iter += n;
return n;
}
};
#endif
#endif // !defined(nsCharTraits_h___)

View File

@@ -1,269 +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)
*/
/* nsDependentConcatenation.h --- string concatenation machinery lives here, but don't include this file
directly, always get it by including either "nsAString.h" or one of the compatibility headers */
#ifndef nsDependentConcatenation_h___
#define nsDependentConcatenation_h___
/**
NOT FOR USE BY HUMANS
Instances of this class only exist as anonymous temporary results from |operator+()|.
This is the machinery that makes string concatenation efficient. No allocations or
character copies are required unless and until a final assignment is made. It works
its magic by overriding and forwarding calls to |GetReadableFragment()|.
Note: |nsDependentConcatenation| imposes some limits on string concatenation with |operator+()|.
- no more than 33 strings, e.g., |s1 + s2 + s3 + ... s32 + s33|
- left to right evaluation is required ... do not use parentheses to override this
In practice, neither of these is onerous. Parentheses do not change the semantics of the
concatenation, only the order in which the result is assembled ... so there's no reason
for a user to need to control it. Too many strings summed together can easily be worked
around with an intermediate assignment. I wouldn't have the parentheses limitation if I
assigned the identifier mask starting at the top, the first time anybody called
|GetReadableFragment()|.
*/
class NS_COM nsDependentConcatenation
: public nsAPromiseString
{
public:
typedef nsDependentConcatenation self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (aFragment.GetIDAsInt() & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.SetID(aFragment.GetIDAsInt() & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.SetID(aFragment.GetIDAsInt() | mFragmentIdentifierMask);
return kRightString;
}
public:
nsDependentConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsDependentConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsDependentConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsDependentConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool IsDependentOn( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
class NS_COM nsDependentCConcatenation
: public nsAPromiseCString
{
public:
typedef nsDependentCConcatenation self_type;
typedef char char_type;
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (aFragment.GetIDAsInt() & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.SetID(aFragment.GetIDAsInt() & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.SetID(aFragment.GetIDAsInt() | mFragmentIdentifierMask);
return kRightString;
}
public:
nsDependentCConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsDependentCConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsDependentCConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsDependentCConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool IsDependentOn( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
/*
How shall we provide |operator+()|?
What would it return? It has to return a stack based object, because the client will
not be given an opportunity to handle memory management in an expression like
myWritableString = stringA + stringB + stringC;
...so the `obvious' answer of returning a new |nsSharedString| is no good. We could
return an |nsString|, if that name were in scope here, though there's no telling what the client
will really want to do with the result. What might be better, though,
is to return a `promise' to concatenate some strings...
By making |nsDependentConcatenation| inherit from readable strings, we automatically handle
assignment and other interesting uses within writable strings, plus we drastically reduce
the number of cases we have to write |operator+()| for. The cost is extra temporary concat strings
in the evaluation of strings of '+'s, e.g., |A + B + C + D|, and that we have to do some work
to implement the virtual functions of readables.
*/
inline
const nsDependentConcatenation
operator+( const nsDependentConcatenation& lhs, const nsAString& rhs )
{
return nsDependentConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsDependentCConcatenation
operator+( const nsDependentCConcatenation& lhs, const nsACString& rhs )
{
return nsDependentCConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsDependentConcatenation
operator+( const nsAString& lhs, const nsAString& rhs )
{
return nsDependentConcatenation(lhs, rhs);
}
inline
const nsDependentCConcatenation
operator+( const nsACString& lhs, const nsACString& rhs )
{
return nsDependentCConcatenation(lhs, rhs);
}
#if 0
inline
const nsDependentConcatenation
nsDependentConcatenation::operator+( const string_type& rhs ) const
{
return nsDependentConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
inline
const nsDependentCConcatenation
nsDependentCConcatenation::operator+( const string_type& rhs ) const
{
return nsDependentCConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
#endif
#endif /* !defined(nsDependentConcatenation_h___) */

View File

@@ -1,145 +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)
*/
#ifndef nsDependentString_h___
#define nsDependentString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
/*
...this class wraps a constant literal string and lets it act like an |const nsAString|.
Use it like this:
SomeFunctionTakingACString( nsDependentCString(myCharPtr) );
This class just holds a pointer. If you don't supply the length, it must calculate it.
No copying or allocations are performed.
See also |NS_LITERAL_STRING| and |NS_LITERAL_CSTRING| when you have a quoted string you want to
use as a |const nsAString|.
*/
class NS_COM nsDependentString
: public nsAFlatString
{
public:
void
Rebind( const PRUnichar* aPtr )
{
mHandle.DataStart(aPtr);
mHandle.DataEnd(aPtr ? (aPtr+nsCharTraits<PRUnichar>::length(aPtr)) : 0);
}
void
Rebind( const PRUnichar* aStartPtr, const PRUnichar* aEndPtr )
{
mHandle.DataStart(aStartPtr);
mHandle.DataEnd(aEndPtr);
}
void
Rebind( const PRUnichar* aPtr, PRUint32 aLength )
{
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller binding a dependent string doesn't know the real length. Please pick the appropriate call.");
Rebind(aPtr);
}
else
Rebind(aPtr, aPtr+aLength);
}
nsDependentString( const PRUnichar* aStartPtr, const PRUnichar* aEndPtr ) { Rebind(aStartPtr, aEndPtr); }
nsDependentString( const PRUnichar* aPtr, PRUint32 aLength ) { Rebind(aPtr, aLength); }
explicit nsDependentString( const PRUnichar* aPtr ) { Rebind(aPtr); }
// nsDependentString( const nsDependentString& ); // auto-generated copy-constructor OK
// ~nsDependentString(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsDependentString& ); // we're immutable, so no copy-assignment operator
public:
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const { return NS_REINTERPRET_CAST(const nsBufferHandle<PRUnichar>*, &mHandle); }
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const { return NS_REINTERPRET_CAST(const nsBufferHandle<PRUnichar>*, &mHandle); }
private:
nsConstBufferHandle<PRUnichar> mHandle;
};
class NS_COM nsDependentCString
: public nsAFlatCString
{
public:
void
Rebind( const char* aPtr )
{
mHandle.DataStart(aPtr);
mHandle.DataEnd(aPtr ? (aPtr+nsCharTraits<char>::length(aPtr)) : 0);
}
void
Rebind( const char* aStartPtr, const char* aEndPtr )
{
mHandle.DataStart(aStartPtr);
mHandle.DataEnd(aEndPtr);
}
void
Rebind( const char* aPtr, PRUint32 aLength )
{
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller binding a dependent string doesn't know the real length. Please pick the appropriate call.");
Rebind(aPtr);
}
else
Rebind(aPtr, aPtr+aLength);
}
nsDependentCString( const char* aStartPtr, const char* aEndPtr ) { Rebind(aStartPtr, aEndPtr); }
nsDependentCString( const char* aPtr, PRUint32 aLength ) { Rebind(aPtr, aLength); }
explicit nsDependentCString( const char* aPtr ) { Rebind(aPtr); }
// nsDependentCString( const nsDependentCString& ); // auto-generated copy-constructor OK
// ~nsDependentCString(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsDependentCString& ); // we're immutable, so no copy-assignment operator
public:
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const { return NS_REINTERPRET_CAST(const nsBufferHandle<char>*, &mHandle); }
virtual const nsBufferHandle<char>* GetBufferHandle() const { return NS_REINTERPRET_CAST(const nsBufferHandle<char>*, &mHandle); }
private:
nsConstBufferHandle<char> mHandle;
};
#endif /* !defined(nsDependentString_h___) */

View File

@@ -1,182 +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)
*/
#ifndef nsDependentSubstring_h___
#define nsDependentSubstring_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
//
// nsDependentSubstring
//
class NS_COM nsDependentSubstring
: public nsAPromiseString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsDependentConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsDependentConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsDependentSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsDependentSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsDependentSubstring( const nsDependentSubstring& ); // auto-generated copy-constructor should be OK
// ~nsDependentSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsDependentSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool IsDependentOn( const string_type& aString ) const { return mString.IsDependentOn(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
class NS_COM nsDependentCSubstring
: public nsAPromiseCString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsDependentConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsDependentConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsDependentCSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsDependentCSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsDependentCSubstring( const nsDependentCSubstring& ); // auto-generated copy-constructor should be OK
// ~nsDependentCSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsDependentCSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool IsDependentOn( const string_type& aString ) const { return mString.IsDependentOn(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
inline
const nsDependentCSubstring
Substring( const nsACString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsDependentCSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsDependentSubstring
Substring( const nsAString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsDependentSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsDependentCSubstring
Substring( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return nsDependentCSubstring(aStart, aEnd);
}
inline
const nsDependentSubstring
Substring( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return nsDependentSubstring(aStart, aEnd);
}
#endif /* !defined(nsDependentSubstring_h___) */

View File

@@ -1,69 +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 XPCOM.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsFragmentedString_h___
#define nsFragmentedString_h___
// WORK IN PROGRESS
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsSharedBufferList_h___
#include "nsSharedBufferList.h"
#endif
class nsFragmentedString
: public nsAString
/*
...
*/
{
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
nsFragmentedString() { }
virtual PRUint32 Length() const;
virtual void SetLength( PRUint32 aNewLength );
// virtual void SetCapacity( PRUint32 aNewCapacity );
// virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
protected:
// virtual void do_AssignFromReadable( const nsAString& );
// virtual void do_AppendFromReadable( const nsAString& );
// virtual void do_InsertFromReadable( const nsAString&, PRUint32 );
// virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const nsAString& );
private:
nsSharedBufferList mBufferList;
};
#endif // !defined(nsFragmentedString_h___)

View File

@@ -1,82 +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)
*/
#ifndef nsLiteralString_h___
#define nsLiteralString_h___
#ifndef nscore_h___
#include "nscore.h"
#endif
#ifndef nsDependentString_h___
#include "nsDependentString.h"
#endif
#if 0
inline
const nsDependentString
literal_string( const PRUnichar* aPtr )
{
return nsDependentString(aPtr);
}
inline
const nsDependentString
literal_string( const PRUnichar* aPtr, PRUint32 aLength )
{
return nsDependentString(aPtr, aLength);
}
inline
const nsDependentCString
literal_string( const char* aPtr )
{
return nsDependentCString(aPtr);
}
inline
const nsDependentCString
literal_string( const char* aPtr, PRUint32 aLength )
{
return nsDependentCString(aPtr, aLength);
}
#endif
#ifdef HAVE_CPP_2BYTE_WCHAR_T
#define NS_L(s) L##s
#define NS_MULTILINE_LITERAL_STRING(s) nsDependentString(NS_REINTERPRET_CAST(const PRUnichar*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) nsDependentString n(NS_REINTERPRET_CAST(const PRUnichar*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
#else
#define NS_L(s) s
#define NS_MULTILINE_LITERAL_STRING(s) NS_ConvertASCIItoUCS2(s, PRUint32(sizeof(s)-1))
#define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) NS_ConvertASCIItoUCS2 n(s, PRUint32(sizeof(s)-1))
#endif
#define NS_LITERAL_STRING(s) NS_STATIC_CAST(const nsAFlatString&, NS_MULTILINE_LITERAL_STRING(NS_L(s)))
#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n,NS_L(s))
#define NS_LITERAL_CSTRING(s) nsDependentCString(s, PRUint32(sizeof(s)-1))
#define NS_NAMED_LITERAL_CSTRING(n,s) nsDependentCString n(s, PRUint32(sizeof(s)-1))
#endif /* !defined(nsLiteralString_h___) */

View File

@@ -1,127 +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)
*/
#ifndef nsLocalString_h___
#define nsLocalString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
/*
...this class wraps a constant literal string and lets it act like an |nsAReadable...|.
Use it like this:
SomeFunctionTakingACString( nsLiteralCString("Hello, World!") );
With some tweaking, I think I can make this work as well...
SomeStringFunc( nsLiteralString( L"Hello, World!" ) );
This class just holds a pointer. If you don't supply the length, it must calculate it.
No copying or allocations are performed.
|const nsLocalString&| appears frequently in interfaces because it
allows the automatic conversion of a |PRUnichar*|.
*/
class NS_COM nsLocalString
: public nsAFlatString
{
public:
explicit
nsLocalString( const PRUnichar* aLiteral )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral))
{
// nothing else to do here
}
nsLocalString( const PRUnichar* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(PRUnichar*, aLiteral), NS_CONST_CAST(PRUnichar*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(PRUnichar*, aLiteral)+nsCharTraits<PRUnichar>::length(aLiteral)) : NS_CONST_CAST(PRUnichar*, aLiteral));
}
}
// nsLocalString( const nsLocalString& ); // auto-generated copy-constructor OK
// ~nsLocalString(); // auto-generated destructor OK
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<PRUnichar> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalString& ); // we're immutable
};
class NS_COM nsLocalCString
: public nsAFlatCString
{
public:
explicit
nsLocalCString( const char* aLiteral )
: mHandle(NS_CONST_CAST(char*, aLiteral), aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral))
{
// nothing else to do here
}
nsLocalCString( const char* aLiteral, PRUint32 aLength )
: mHandle(NS_CONST_CAST(char*, aLiteral), NS_CONST_CAST(char*, aLiteral)+aLength)
{
// This is an annoying hack. Callers should be fixed to use the other
// constructor if they don't really know the length.
if ( aLength == PRUint32(-1) )
{
// NS_WARNING("Tell scc: Caller constructing a string doesn't know the real length. Please use the other constructor.");
mHandle.DataEnd(aLiteral ? (NS_CONST_CAST(char*, aLiteral)+nsCharTraits<char>::length(aLiteral)) : NS_CONST_CAST(char*, aLiteral));
}
}
// nsLocalCString( const nsLocalCString& ); // auto-generated copy-constructor OK
// ~nsLocalCString(); // auto-generated destructor OK
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const { return &mHandle; }
virtual const nsBufferHandle<char>* GetBufferHandle() const { return &mHandle; }
private:
nsBufferHandle<char> mHandle;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsLocalCString& ); // we're immutable
};
#endif /* !defined(nsLocalString_h___) */

View File

@@ -1,96 +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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef nsPrintfCString_h___
#define nsPrintfCString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
/**
* |nsPrintfCString| lets you use a formated |printf| string as an |nsAReadableCString|.
*
* myCStr += nsPrintfCString("%f", 13.917);
* // ...a general purpose substitute for |AppendFloat|
*
* For longer patterns, you'll want to use the constructor that takes a length
*
* nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
*
* Exceding the default size (which you must specify in the constructor, it is not determined)
* causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
* cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
* This class is intended to be useful for numbers and short
* strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
* wide version of this class, since wide |printf| is not generally available. That means
* to get a wide version of your formatted data, you must, e.g.,
*
* CopyASCIItoUCS2(nsPrintfCString("%f", 13.917"), myStr);
*
* That's another good reason to avoid this class for anything but numbers ... as strings can be
* much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
*/
class nsPrintfCString
: public nsACString
{
enum { kLocalBufferSize=15 };
// ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
// pinkerton suggests 7. We should measure and decide what's appropriate
public:
explicit nsPrintfCString( const char* format, ... );
nsPrintfCString( size_t n, const char* format, ...);
~nsPrintfCString();
virtual PRUint32 Length() const;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
// virtual PRBool GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const;
private:
char* mStart;
PRUint32 mLength;
char mLocalBuffer[ kLocalBufferSize + 1 ];
};
#endif // !defined(nsPrintfCString_h___)

View File

@@ -1,82 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsPrivateSharableString_h___
#define nsPrivateSharableString_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
#endif
/**
* This class is part of the machinery that makes
* most string implementations in this family share their underlying buffers
* when convenient. It is _not_ part of the abstract string interface,
* though other machinery interested in sharing buffers will know about it.
*
* Normal string clients must _never_ call routines from this interface.
*/
class NS_COM nsPrivateSharableString
{
public:
typedef PRUnichar char_type;
public:
virtual ~nsPrivateSharableString() {}
virtual PRUint32 GetImplementationFlags() const;
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
};
class NS_COM nsPrivateSharableCString
{
public:
typedef char char_type;
public:
virtual ~nsPrivateSharableCString() {}
virtual PRUint32 GetImplementationFlags() const;
virtual const nsBufferHandle<char_type>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char_type>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
/**
* |GetBufferHandle()| will return either |0|, or a reasonable pointer.
* The meaning of |0| is that the string points to a non-contiguous or else empty representation.
* Otherwise |GetBufferHandle()| returns a handle that points to the single contiguous hunk of characters
* that make up this string.
*/
};
#endif // !defined(nsPrivateSharableString_h___)

View File

@@ -1,269 +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)
*/
/* nsPromiseConcatenation.h --- string concatenation machinery lives here, but don't include this file
directly, always get it by including either "nsAString.h" or one of the compatibility headers */
#ifndef nsPromiseConcatenation_h___
#define nsPromiseConcatenation_h___
/**
NOT FOR USE BY HUMANS
Instances of this class only exist as anonymous temporary results from |operator+()|.
This is the machinery that makes string concatenation efficient. No allocations or
character copies are required unless and until a final assignment is made. It works
its magic by overriding and forwarding calls to |GetReadableFragment()|.
Note: |nsPromiseConcatenation| imposes some limits on string concatenation with |operator+()|.
- no more than 33 strings, e.g., |s1 + s2 + s3 + ... s32 + s33|
- left to right evaluation is required ... do not use parentheses to override this
In practice, neither of these is onerous. Parentheses do not change the semantics of the
concatenation, only the order in which the result is assembled ... so there's no reason
for a user to need to control it. Too many strings summed together can easily be worked
around with an intermediate assignment. I wouldn't have the parentheses limitation if I
assigned the identifier mask starting at the top, the first time anybody called
|GetReadableFragment()|.
*/
class NS_COM nsPromiseConcatenation
: public nsAPromiseString
{
public:
typedef nsPromiseConcatenation self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
class NS_COM nsPromiseCConcatenation
: public nsAPromiseCString
{
public:
typedef nsPromiseCConcatenation self_type;
typedef char char_type;
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char_type* GetReadableFragment( nsReadableFragment<char_type>&, nsFragmentRequest, PRUint32 ) const;
virtual char_type* GetWritableFragment( nsWritableFragment<char_type>&, nsFragmentRequest, PRUint32 ) { return 0; }
enum { kLeftString, kRightString };
int
GetCurrentStringFromFragment( const nsReadableFragment<char_type>& aFragment ) const
{
return (NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & mFragmentIdentifierMask) ? kRightString : kLeftString;
}
int
SetLeftStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) & ~mFragmentIdentifierMask);
return kLeftString;
}
int
SetRightStringInFragment( nsReadableFragment<char_type>& aFragment ) const
{
aFragment.mFragmentIdentifier = NS_REINTERPRET_CAST(void*, NS_REINTERPRET_CAST(PRUint32, aFragment.mFragmentIdentifier) | mFragmentIdentifierMask);
return kRightString;
}
public:
nsPromiseCConcatenation( const string_type& aLeftString, const string_type& aRightString, PRUint32 aMask = 1 )
: mFragmentIdentifierMask(aMask)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
nsPromiseCConcatenation( const self_type& aLeftString, const string_type& aRightString )
: mFragmentIdentifierMask(aLeftString.mFragmentIdentifierMask<<1)
{
mStrings[kLeftString] = &aLeftString;
mStrings[kRightString] = &aRightString;
}
// nsPromiseCConcatenation( const self_type& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCConcatenation(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const self_type& ); // we're immutable, you can't assign into a concatenation
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& ) const;
// virtual PRBool PromisesExactly( const string_type& ) const;
// const self_type operator+( const string_type& rhs ) const;
PRUint32 GetFragmentIdentifierMask() const { return mFragmentIdentifierMask; }
private:
void operator+( const self_type& ); // NOT TO BE IMPLEMENTED
// making this |private| stops you from over parenthesizing concatenation expressions, e.g., |(A+B) + (C+D)|
// which would break the algorithm for distributing bits in the fragment identifier
private:
const string_type* mStrings[2];
PRUint32 mFragmentIdentifierMask;
};
/*
How shall we provide |operator+()|?
What would it return? It has to return a stack based object, because the client will
not be given an opportunity to handle memory management in an expression like
myWritableString = stringA + stringB + stringC;
...so the `obvious' answer of returning a new |nsSharedString| is no good. We could
return an |nsString|, if that name were in scope here, though there's no telling what the client
will really want to do with the result. What might be better, though,
is to return a `promise' to concatenate some strings...
By making |nsPromiseConcatenation| inherit from readable strings, we automatically handle
assignment and other interesting uses within writable strings, plus we drastically reduce
the number of cases we have to write |operator+()| for. The cost is extra temporary concat strings
in the evaluation of strings of '+'s, e.g., |A + B + C + D|, and that we have to do some work
to implement the virtual functions of readables.
*/
inline
const nsPromiseConcatenation
operator+( const nsPromiseConcatenation& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseCConcatenation
operator+( const nsPromiseCConcatenation& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs, lhs.GetFragmentIdentifierMask()<<1);
}
inline
const nsPromiseConcatenation
operator+( const nsAString& lhs, const nsAString& rhs )
{
return nsPromiseConcatenation(lhs, rhs);
}
inline
const nsPromiseCConcatenation
operator+( const nsACString& lhs, const nsACString& rhs )
{
return nsPromiseCConcatenation(lhs, rhs);
}
#if 0
inline
const nsPromiseConcatenation
nsPromiseConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
inline
const nsPromiseCConcatenation
nsPromiseCConcatenation::operator+( const string_type& rhs ) const
{
return nsPromiseCConcatenation(*this, rhs, mFragmentIdentifierMask<<1);
}
#endif
#endif /* !defined(nsPromiseConcatenation_h___) */

View File

@@ -1,170 +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)
*/
#ifndef nsPromiseFlatString_h___
#define nsPromiseFlatString_h___
#ifndef nsSharableString_h___
#include "nsSharableString.h"
#endif
/**
* WARNING:
*
* Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last resort,
* and this may be necessary when dealing with legacy or OS calls, but in general,
* requiring a zero-terminated contiguous hunk of characters kills many of the performance
* wins the string classes offer. Write your own code to use |nsA[C]String&|s for parameters.
* Write your string proccessing algorithms to exploit iterators. If you do this, you
* will benefit from being able to chain operations without copying or allocating and your
* code will be significantly more efficient. Remember, a function that takes an
* |const nsA[C]String&| can always be passed a raw character pointer by wrapping it (for free)
* in a |nsLocal[C]String|. But a function that takes a character pointer always has the
* potential to force allocation and copying.
*
*
* How to use it:
*
* Like all `promises', a |nsPromiseFlat[C]String| doesn't own the characters it promises.
* You must never use it to promise characters out of a string with a shorter lifespan.
* The typical use will be something like this
*
* SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD
*
* Here's a BAD use:
*
* const char* buffer = PromiseFlatCString(aCString).get();
* SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer
*
* A |nsPromiseFlat[C]String| doesn't support non-|const| access (you can't use it to make
* changes back into the original string). To help you avoid that, the only way to make
* one is with the function |PromiseFlat[C]String|, which produce a |const| instance.
* ``What if I need to keep a promise around for a little while?'' you might ask.
* In that case, you can keep a reference, like so
*
* const nsPromiseFlatString& flat = PromiseFlatString(aString);
* // this reference holds the anonymous temporary alive, but remember, it must _still_
* // have a lifetime shorter than that of |aString|
*
* SomeOSFunction(flat.get());
* SomeOtherOSFunction(flat.get());
*
*
* How does it work?
*
* A |nsPromiseFlat[C]String| is just a wrapper for another string. If you apply it to
* a string that happens to be flat, your promise is just a reference to that other string
* and all calls are forwarded through to it. If you apply it to a non-flat string,
* then a temporary flat string is created for you, by allocating and copying. In the unlikely
* event that you end up assigning the result into a sharing string (e.g., |nsSharable[C]String|),
* the right thing happens.
*/
class NS_COM nsPromiseFlatString
: public nsAFlatString /* , public nsAPromiseString */
{
friend const nsPromiseFlatString PromiseFlatString( const nsAString& );
public:
nsPromiseFlatString( const nsPromiseFlatString& );
protected:
nsPromiseFlatString() : mPromisedString(&mFlattenedString) { }
explicit nsPromiseFlatString( const nsAString& aString );
// things we want to forward to the string we are promising
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<PRUnichar>* GetSharedBufferHandle() const;
virtual PRBool IsDependentOn( const nsAString& ) const;
// things we are forwarding now, but won't when we finally fix obsolete/nsString et al
public:
virtual const PRUnichar* get() const;
virtual PRUint32 Length() const;
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseFlatString& );
private:
nsSharableString mFlattenedString;
const nsAFlatString* mPromisedString;
};
class NS_COM nsPromiseFlatCString
: public nsAFlatCString /* , public nsAPromiseCString */
{
friend const nsPromiseFlatCString PromiseFlatCString( const nsACString& );
public:
nsPromiseFlatCString( const nsPromiseFlatCString& );
protected:
nsPromiseFlatCString() : mPromisedString(&mFlattenedString) { }
explicit nsPromiseFlatCString( const nsACString& aString );
// things we want to forward to the string we are promising
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char>* GetBufferHandle() const;
virtual const nsSharedBufferHandle<char>* GetSharedBufferHandle() const;
virtual PRBool IsDependentOn( const nsACString& ) const;
// things we are forwarding now, but won't when we finally fix obsolete/nsString et al
public:
virtual const char* get() const;
virtual PRUint32 Length() const;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseFlatCString& );
private:
nsSharableCString mFlattenedString;
const nsAFlatCString* mPromisedString;
};
inline
const nsPromiseFlatString
PromiseFlatString( const nsAString& aString )
{
return nsPromiseFlatString(aString);
}
inline
const nsPromiseFlatCString
PromiseFlatCString( const nsACString& aString )
{
return nsPromiseFlatCString(aString);
}
#endif /* !defined(nsPromiseFlatString_h___) */

View File

@@ -1,182 +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)
*/
#ifndef nsPromiseSubstring_h___
#define nsPromiseSubstring_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
//
// nsPromiseSubstring
//
class NS_COM nsPromiseSubstring
: public nsAPromiseString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsAString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseSubstring( const nsPromiseSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
class NS_COM nsPromiseCSubstring
: public nsAPromiseCString
/*
NOT FOR USE BY HUMANS (mostly)
...not unlike |nsPromiseConcatenation|. Instances of this class exist only as anonymous
temporary results from |Substring()|. Like |nsPromiseConcatenation|, this class only
holds a pointer, no string data of its own. It does its magic by overriding and forwarding
calls to |GetReadableFragment()|.
*/
{
typedef nsACString string_type;
typedef string_type::const_iterator const_iterator;
protected:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 ) { return 0; }
public:
nsPromiseCSubstring( const string_type& aString, PRUint32 aStartPos, PRUint32 aLength )
: mString(aString),
mStartPos( NS_MIN(aStartPos, aString.Length()) ),
mLength( NS_MIN(aLength, aString.Length()-mStartPos) )
{
// nothing else to do here
}
nsPromiseCSubstring( const const_iterator& aStart, const const_iterator& aEnd )
: mString(aStart.string())
{
const_iterator zeroPoint;
mString.BeginReading(zeroPoint);
mStartPos = Distance(zeroPoint, aStart);
mLength = Distance(aStart, aEnd);
}
// nsPromiseCSubstring( const nsPromiseCSubstring& ); // auto-generated copy-constructor should be OK
// ~nsPromiseCSubstring(); // auto-generated destructor OK
private:
// NOT TO BE IMPLEMENTED
void operator=( const nsPromiseCSubstring& ); // we're immutable, you can't assign into a substring
public:
virtual PRUint32 Length() const;
virtual PRBool Promises( const string_type& aString ) const { return mString.Promises(aString); }
private:
const string_type& mString;
PRUint32 mStartPos;
PRUint32 mLength;
};
inline
const nsPromiseCSubstring
Substring( const nsACString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseCSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseSubstring
Substring( const nsAString& aString, PRUint32 aStartPos, PRUint32 aSubstringLength )
{
return nsPromiseSubstring(aString, aStartPos, aSubstringLength);
}
inline
const nsPromiseCSubstring
Substring( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return nsPromiseCSubstring(aStart, aEnd);
}
inline
const nsPromiseSubstring
Substring( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return nsPromiseSubstring(aStart, aEnd);
}
#endif /* !defined(nsPromiseSubstring_h___) */

View File

@@ -1,293 +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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
* Johnny Stenbeck <jst@netscape.com>
*
*/
#ifndef nsReadableUtils_h___
#define nsReadableUtils_h___
/**
* I guess all the routines in this file are all mis-named.
* According to our conventions, they should be |NS_xxx|.
*/
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsAStringGenerator_h___
#include "nsAStringGenerator.h"
#endif
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
NS_COM void CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest );
NS_COM void CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsAString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewCString( const nsACString& aSource );
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs a encoding conversion by converting 16-bit wide characters down to UTF8 encoded 8-bits wide string copying |aSource| to your new buffer.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |char| buffer you must free with |nsMemory::Free|.
*/
NS_COM char* ToNewUTF8String( const nsAString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource a 16-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsAString& aSource );
/**
* Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
* Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
*
* @param aSource an 8-bit wide string
* @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
*/
NS_COM PRUnichar* ToNewUnicode( const nsACString& aSource );
/**
* Copies |aLength| 16-bit characters from the start of |aSource| to the
* |PRUnichar| buffer |aDest|.
*
* After this operation |aDest| is not null terminated.
*
* @param aSource a 16-bit wide string
* @param aSrcOffset start offset in the source string
* @param aDest a |PRUnichar| buffer
* @param aLength the number of 16-bit characters to copy
* @return pointer to destination buffer - identical to |aDest|
*/
NS_COM PRUnichar* CopyUnicodeTo( const nsAString& aSource,
PRUint32 aSrcOffset,
PRUnichar* aDest,
PRUint32 aLength );
/**
* Copies 16-bit characters between iterators |aSrcStart| and
* |aSrcEnd| to the writable string |aDest|. Similar to the
* |nsString::Mid| method.
*
* After this operation |aDest| is not null terminated.
*
* @param aSrcStart start source iterator
* @param aSrcEnd end source iterator
* @param aDest destination for the copy
*/
NS_COM void CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest );
/**
* Appends 16-bit characters between iterators |aSrcStart| and
* |aSrcEnd| to the writable string |aDest|.
*
* After this operation |aDest| is not null terminated.
*
* @param aSrcStart start source iterator
* @param aSrcEnd end source iterator
* @param aDest destination for the copy
*/
NS_COM void AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest );
/**
* Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
*
* @param aString a 16-bit wide string to scan
*/
NS_COM PRBool IsASCII( const nsAString& aString );
/**
* Converts case in place in the argument string.
*/
NS_COM void ToUpperCase( nsAString& );
NS_COM void ToUpperCase( nsACString& );
NS_COM void ToLowerCase( nsAString& );
NS_COM void ToLowerCase( nsACString& );
/**
* Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|.
*
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
* point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
*
* Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
* If we need something faster, then we can implement that later.
*/
NS_COM PRBool FindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
NS_COM PRBool FindInReadable( const nsACString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& );
NS_COM PRBool CaseInsensitiveFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
NS_COM PRBool CaseInsensitiveFindInReadable( const nsACString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& );
/**
* Finds the rightmost occurance of |aPattern|
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
* point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
*
* Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
* If we need something faster, then we can implement that later.
*/
NS_COM PRBool RFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
NS_COM PRBool RFindInReadable( const nsACString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& );
/**
* Finds the leftmost occurance of |aChar|, if any in the range
* |aSearchStart|..|aSearchEnd|.
*
* Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to
* point to the match. If no match was found, returns |PR_FALSE| and
* makes |aSearchStart == aSearchEnd|.
*/
NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, const nsReadingIterator<PRUnichar>& aSearchEnd );
NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, const nsReadingIterator<char>& aSearchEnd );
/**
* Finds the number of occurences of |aChar| in the string |aStr|
*/
NS_COM PRUint32 CountCharInReadable( const nsAString& aStr,
PRUnichar aChar );
NS_COM PRUint32 CountCharInReadable( const nsACString& aStr,
char aChar );
/*
|nsSubstituteC?String|:
this is currently a naive implementation leveraging |FindInReadable|. I have a better
algorithm in mind -- Gonnet, Baeza-Yates `Shift-Or' searching which is linear and simple
to implement (not quite as simple as re-using |FindInReadable|, though :-).
*/
class NS_COM nsSubstituteString
: public nsAStringGenerator
{
public:
nsSubstituteString( const nsAString& aText, const nsAString& aPattern, const nsAString& aReplacement )
: mText(aText),
mPattern(aPattern),
mReplacement(aReplacement),
mNumberOfMatches(-1) // |-1| means `don't know'
{
// nothing else to do here
}
virtual PRUnichar* operator()( PRUnichar* aDestBuffer ) const;
virtual PRUint32 Length() const;
virtual PRUint32 MaxLength() const;
virtual PRBool IsDependentOn( const nsAString& ) const;
private:
void CountMatches() const;
private:
const nsAString& mText;
const nsAString& mPattern;
const nsAString& mReplacement;
/* mutable */ PRInt32 mNumberOfMatches;
};
class NS_COM nsSubstituteCString
: public nsACStringGenerator
{
public:
nsSubstituteCString( const nsACString& aText, const nsACString& aPattern, const nsACString& aReplacement )
: mText(aText),
mPattern(aPattern),
mReplacement(aReplacement),
mNumberOfMatches(-1) // |-1| means `don't know'
{
// nothing else to do here
}
virtual char* operator()( char* aDestBuffer ) const;
virtual PRUint32 Length() const;
virtual PRUint32 MaxLength() const;
virtual PRBool IsDependentOn( const nsACString& ) const;
private:
void CountMatches() const;
private:
const nsACString& mText;
const nsACString& mPattern;
const nsACString& mReplacement;
/* mutable */ PRInt32 mNumberOfMatches;
};
#endif // !defined(nsReadableUtils_h___)

View File

@@ -1,104 +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)
*/
/* nsSharableString.h --- a string implementation that shares its underlying storage */
#ifndef nsSharableString_h___
#define nsSharableString_h___
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
#endif
//-------1---------2---------3---------4---------5---------6---------7---------8
/**
* Not yet ready for non-|const| access
*/
class NS_COM nsSharableString
: public nsAFlatString
{
public:
typedef nsSharableString self_type;
typedef PRUnichar char_type;
typedef nsAString string_type;
public:
nsSharableString() { }
nsSharableString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
explicit nsSharableString( const string_type& aReadable ) { assign(aReadable); }
explicit nsSharableString( const nsSharedBufferHandle<char_type>* aHandle ) : mBuffer(aHandle) { }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
protected:
nsAutoBufferHandle<char_type> mBuffer;
};
class NS_COM nsSharableCString
: public nsAFlatCString
{
public:
typedef nsSharableCString self_type;
typedef char char_type;
typedef nsACString string_type;
public:
nsSharableCString() { }
nsSharableCString( const self_type& aOther ) : mBuffer(aOther.mBuffer) { }
explicit nsSharableCString( const string_type& aReadable ) { assign(aReadable); }
explicit nsSharableCString( const nsSharedBufferHandle<char_type>* aHandle ) : mBuffer(aHandle) { }
self_type&
operator=( const string_type& aReadable )
{
assign(aReadable);
return *this;
}
protected:
void assign( const string_type& );
virtual const nsSharedBufferHandle<char_type>* GetSharedBufferHandle() const;
protected:
nsAutoBufferHandle<char_type> mBuffer;
};
#endif /* !defined(nsSharableString_h___) */

View File

@@ -1,224 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSharedBufferList_h___
#define nsSharedBufferList_h___
#ifndef nsBufferHandle_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#endif
#ifndef nscore_h___
#include "nscore.h"
// for |PRUnichar|
#endif
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsDependentString_h___
#include "nsDependentString.h"
#endif
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
// for |NS_AllocateContiguousHandleWithData|
#endif
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class NS_COM nsSharedBufferList
{
public:
class Buffer
: public nsFlexBufferHandle<PRUnichar>
{
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd, PRBool aIsSingleAllocation=PR_FALSE )
: nsFlexBufferHandle<PRUnichar>(aDataStart, aDataEnd, aStorageStart, aStorageEnd)
{
if ( aIsSingleAllocation )
this->mFlags |= this->kIsSingleAllocationWithBuffer;
}
/**
* These buffers will be `owned' by the list, and only the
* the list itself will be allowed to delete member |Buffer|s,
* therefore, we cannot use the inherited |AcquireReference|
* and |ReleaseReference|, as they use the model that the
* buffer manages its own lifetime.
*/
void
AcquireNonOwningReference() const
{
Buffer* mutable_this = NS_CONST_CAST(Buffer*, this);
mutable_this->set_refcount( get_refcount()+1 );
}
void
ReleaseNonOwningReference() const
{
Buffer* mutable_this = NS_CONST_CAST(Buffer*, this);
mutable_this->set_refcount( get_refcount()-1 );
}
Buffer* mPrev;
Buffer* mNext;
private:
// pass-by-value is explicitly denied
Buffer( const Buffer& ); // NOT TO BE IMPLEMENTED
void operator=( const Buffer& ); // NOT TO BE IMPLEMENTED
};
struct Position
{
Buffer* mBuffer;
PRUnichar* mPosInBuffer;
Position() { }
Position( Buffer* aBuffer, PRUnichar* aPosInBuffer ) : mBuffer(aBuffer), mPosInBuffer(aPosInBuffer) { }
// Position( const Position& ); -- auto-generated copy-constructor OK
// Position& operator=( const Position& ); -- auto-generated copy-assignment OK
// ~Position(); -- auto-generated destructor OK
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
explicit
Position( const nsReadingIterator<PRUnichar>& aIter )
: mBuffer( NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier)) ),
mPosInBuffer( NS_CONST_CAST(PRUnichar*, aIter.get()) )
{
// nothing else to do here
}
// iff |aIter| is a valid iterator into a |nsSharedBufferList|
Position&
operator=( const nsReadingIterator<PRUnichar>& aIter )
{
mBuffer = NS_CONST_CAST(Buffer*, NS_REINTERPRET_CAST(const Buffer*, aIter.fragment().mFragmentIdentifier));
mPosInBuffer = NS_CONST_CAST(PRUnichar*, aIter.get());
return *this;
}
void PointTo( Buffer* aBuffer, PRUnichar* aPosInBuffer ) { mBuffer=aBuffer; mPosInBuffer=aPosInBuffer; }
void PointBefore( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataStart()); }
void PointAfter( Buffer* aBuffer ) { PointTo(aBuffer, aBuffer->DataEnd()); }
// Position( const Position& ); -- automatically generated copy-constructor is OK
// Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK
// don't want to provide this as |operator-|, since that might imply O(1)
static ptrdiff_t Distance( const Position&, const Position& );
};
public:
nsSharedBufferList( Buffer* aBuffer = 0 )
: mFirstBuffer(aBuffer),
mLastBuffer(aBuffer),
mTotalDataLength(0)
{
if ( aBuffer )
{
aBuffer->mPrev = aBuffer->mNext = 0;
mTotalDataLength = aBuffer->DataLength();
}
}
virtual ~nsSharedBufferList();
private:
// pass-by-value is explicitly denied
nsSharedBufferList( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSharedBufferList& ); // NOT TO BE IMPLEMENTED
public:
void LinkBuffer( Buffer*, Buffer*, Buffer* );
Buffer* UnlinkBuffer( Buffer* );
enum SplitDisposition // when splitting a buffer in two...
{
kSplitCopyRightData, // copy the data right of the split point to a new buffer
kSplitCopyLeastData, // copy the smaller amount of data to the new buffer
kSplitCopyLeftData // copy the data left of the split point to a new buffer
};
void SplitBuffer( const Position&, SplitDisposition = kSplitCopyLeastData );
static
Buffer*
NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalCapacity = 1 )
{
typedef Buffer* Buffer_ptr;
return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), nsDependentString(aData, aDataLength), aAdditionalCapacity);
}
static
Buffer*
NewSingleAllocationBuffer( const nsAString& aReadable, PRUint32 aAdditionalCapacity = 1 )
{
typedef Buffer* Buffer_ptr;
return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), aReadable, aAdditionalCapacity);
}
static
Buffer*
NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
{
return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd);
}
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@@ -1,203 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#ifndef nsSlidingString_h___
#define nsSlidingString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
#ifndef nsSharedBufferList_h___
#include "nsSharedBufferList.h"
#endif
/**
* Maintains the sequence from the prev-most referenced buffer to the last buffer.
* As prev-most buffers become un-referenced, they are unlinked from the list
* and destroyed.
*
* One or more |nsSlidingSubstring|s may reference into the list. Each |nsSlidingSubstring|
* holds a reference into the prev-most buffer intersecting the
* substring it describes. The destructor of a |nsSlidingSubstring| releases this
* reference, allowing the buffer list to destroy the contiguous prefix of
* unreferenced buffers.
*
* A single instance of |nsSlidingString| may reference this list.
* Through that interface, new data can be appended onto the next-most end
* of the list. |nsSlidingString| also the client to advance its starting point.
*
*/
class NS_COM nsSlidingSharedBufferList
: public nsSharedBufferList
{
public:
nsSlidingSharedBufferList( Buffer* aBuffer ) : nsSharedBufferList(aBuffer), mRefCount(0) { }
void AcquireReference() { ++mRefCount; }
void ReleaseReference() { if ( !--mRefCount ) delete this; }
void DiscardUnreferencedPrefix( Buffer* );
private:
PRUint32 mRefCount;
};
class nsSlidingString;
/**
* a substring over a buffer list, this
*/
class NS_COM nsSlidingSubstring
: virtual public nsAPromiseString
{
friend class nsSlidingString;
public:
typedef nsSlidingSharedBufferList::Buffer Buffer;
typedef nsSlidingSharedBufferList::Position Position;
nsSlidingSubstring()
: mStart(0,0),
mEnd(0,0),
mBufferList(0),
mLength(0)
{
// nothing else to do here
}
nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor
nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
nsSlidingSubstring( const nsSlidingString& );
nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd );
explicit nsSlidingSubstring( const nsAString& );
// copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list
void Rebind( const nsSlidingSubstring& );
void Rebind( const nsSlidingSubstring&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
void Rebind( const nsSlidingString& );
void Rebind( const nsSlidingString&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
void Rebind( const nsAString& );
~nsSlidingSubstring();
virtual PRUint32 Length() const { return mLength; }
protected:
nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList );
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
private:
// can't assign into me, I'm a read-only reference
void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED
void
init_range_from_buffer_list()
// used only from constructors
{
mStart.PointBefore(mBufferList->GetFirstBuffer());
mEnd.PointAfter(mBufferList->GetLastBuffer());
mLength = PRUint32(Position::Distance(mStart, mEnd));
}
void
acquire_ownership_of_buffer_list() const
// used only from constructors and |Rebind|, requires |mStart| already be initialized
{
mBufferList->AcquireReference();
mStart.mBuffer->AcquireNonOwningReference();
}
void
release_ownership_of_buffer_list()
{
if ( mBufferList )
{
mStart.mBuffer->ReleaseNonOwningReference();
mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer);
mBufferList->ReleaseReference();
}
}
protected:
Position mStart;
Position mEnd;
nsSlidingSharedBufferList* mBufferList;
PRUint32 mLength;
};
/**
* An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class.
*
*/
class NS_COM nsSlidingString
: virtual public nsAPromiseString,
private nsSlidingSubstring
{
friend class nsSlidingSubstring;
public:
nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// ...created by consuming ownership of a buffer ... |aStorageStart| must point to something
// that it will be OK for the slidking string to call |nsMemory::Free| on
virtual PRUint32 Length() const { return mLength; }
// you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done
void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd );
// void Append( ... ); do you want some |Append|s that copy the supplied data?
void DiscardPrefix( const nsReadingIterator<PRUnichar>& );
// any other way you want to do this?
protected:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) { return 0; }
void InsertReadable( const nsAString&, const nsReadingIterator<PRUnichar>& ); // ...to implement |nsScannerString::UngetReadable|
private:
void
acquire_ownership_of_buffer_list() const
// used only from constructors and |Rebind|, requires |mStart| already be initialized
{
mBufferList->AcquireReference();
mStart.mBuffer->AcquireNonOwningReference();
}
nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED
};
#endif // !defined(nsSlidingString_h___)

View File

@@ -1,37 +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)
*/
/* nsStringDefines.h --- preprocessor definitions common across all string files */
#ifndef nsStringDefines_h___
#define nsStringDefines_h___
#if !defined(DEBUG) || !defined(DEBUG_STRING)
#define DEBUG_STRING 0
#endif
#if !defined(DEBUG) || !defined(DEBUG_STRING_STATS)
#define DEBUG_STRING_STATS 0
#endif
#endif

View File

@@ -1,125 +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)
*/
/* nsStringFragment.h --- machinery that makes string iterators work */
#ifndef nsStringFragment_h___
#define nsStringFragment_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/**
* An |nsFragmentRequest| is used to tell |GetReadableFragment| and
* |GetWritableFragment| what to do.
*
* @see GetReadableFragment
*/
enum nsFragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt };
/**
* A |nsReadableFragment| provides |const| access to a contiguous hunk of
* string of homogenous units, e.g., bytes (|char|). This doesn't mean it
* represents a flat hunk. It could be a variable length encoding, for
* instance UTF-8. And the fragment itself need not be zero-terminated.
*
* An |nsReadableFragment| is the underlying machinery that lets
* |nsReadingIterator|s work.
*
* @see nsReadingIterator
*/
template <class CharT>
struct nsReadableFragment
{
const CharT* mStart;
const CharT* mEnd;
const void* mFragmentIdentifier;
nsReadableFragment()
: mStart(0), mEnd(0), mFragmentIdentifier(0)
{
// nothing else to do here
}
const void*
GetID() const
{
return mFragmentIdentifier;
}
unsigned long
GetIDAsInt() const
{
typedef char* char_ptr;
typedef unsigned long ulong;
return ulong(char_ptr(mFragmentIdentifier)-char_ptr(0));
}
void
SetID( const void* id )
{
mFragmentIdentifier = id;
}
void
SetID( unsigned long id )
{
typedef char* char_ptr;
typedef void* void_ptr;
mFragmentIdentifier = void_ptr(char_ptr(0)+id);
}
};
/**
* A |nsWritableFragment| provides non-|const| access to a contiguous hunk of
* string of homogenous units, e.g., bytes (|char|). This doesn't mean it
* represents a flat hunk. It could be a variable length encoding, for
* instance UTF-8. And the fragment itself need not be zero-terminated.
*
* An |nsWritableFragment| is the underlying machinery that lets
* |nsWritingIterator|s work.
*
* @see nsWritingIterator
*/
template <class CharT>
struct nsWritableFragment
{
CharT* mStart;
CharT* mEnd;
void* mFragmentIdentifier;
nsWritableFragment()
: mStart(0), mEnd(0), mFragmentIdentifier(0)
{
// nothing else to do here
}
};
#endif /* !defined(nsStringFragment_h___) */

View File

@@ -1,65 +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)
*/
/* nsStringFwd.h --- forward declarations for string classes */
#ifndef nsStringFwd_h___
#define nsStringFwd_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/**
* @see nsAString.h
*/
class nsAString;
class nsACString;
/**
* @see nsAPromiseString.h
*/
class nsAPromiseString;
class nsAPromiseCString;
/**
* @see nsAFlatString.h
*/
class nsAFlatString;
class nsAFlatCString;
/**
* @see nsDependentString.h
*/
class nsDependentString;
class nsDependentCString;
#endif /* !defined(nsStringFwd_h___) */

View File

@@ -1,436 +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)
*/
#ifndef nsStringIterator_h___
#define nsStringIterator_h___
#ifndef nsStringFragment_h___
#include "nsStringFragment.h"
#endif
#ifndef nsCharTraits_h___
#include "nsCharTraits.h"
#endif
#ifndef nsStringTraits_h___
#include "nsStringTraits.h"
#endif
#ifndef nsAlgorithm_h___
#include "nsAlgorithm.h"
// for |NS_MIN|, |NS_MAX|, and |NS_COUNT|...
#endif
/**
*
* @see nsReadableFragment
* @see nsAString
*/
template <class CharT>
class nsReadingIterator
// : public bidirectional_iterator_tag
{
public:
typedef ptrdiff_t difference_type;
typedef CharT value_type;
typedef const CharT* pointer;
typedef const CharT& reference;
// typedef bidirectional_iterator_tag iterator_category;
private:
friend class nsAString;
friend class nsACString;
typedef typename nsStringTraits<CharT>::abstract_string_type string_type;
nsReadableFragment<CharT> mFragment;
const CharT* mPosition;
const string_type* mOwningString;
public:
nsReadingIterator() { }
// nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
// nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
inline void normalize_forward();
inline void normalize_backward();
pointer
get() const
{
return mPosition;
}
CharT
operator*() const
{
return *get();
}
#if 0
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
// don't like this when |CharT| is a type without members.
pointer
operator->() const
{
return get();
}
#endif
nsReadingIterator<CharT>&
operator++()
{
++mPosition;
normalize_forward();
return *this;
}
nsReadingIterator<CharT>
operator++( int )
{
nsReadingIterator<CharT> result(*this);
++mPosition;
normalize_forward();
return result;
}
nsReadingIterator<CharT>&
operator--()
{
normalize_backward();
--mPosition;
return *this;
}
nsReadingIterator<CharT>
operator--( int )
{
nsReadingIterator<CharT> result(*this);
normalize_backward();
--mPosition;
return result;
}
const nsReadableFragment<CharT>&
fragment() const
{
return mFragment;
}
const string_type&
string() const
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
difference_type
size_forward() const
{
return mFragment.mEnd - mPosition;
}
difference_type
size_backward() const
{
return mPosition - mFragment.mStart;
}
nsReadingIterator<CharT>&
advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a reading iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a reading iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
};
template <class CharT>
class nsWritingIterator
// : public nsReadingIterator<CharT>
{
public:
typedef ptrdiff_t difference_type;
typedef CharT value_type;
typedef CharT* pointer;
typedef CharT& reference;
// typedef bidirectional_iterator_tag iterator_category;
private:
friend class nsAString;
friend class nsACString;
typedef typename nsStringTraits<CharT>::abstract_string_type string_type;
nsWritableFragment<CharT> mFragment;
CharT* mPosition;
string_type* mOwningString;
public:
nsWritingIterator() { }
// nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
// nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
inline void normalize_forward();
inline void normalize_backward();
pointer
get() const
{
return mPosition;
}
reference
operator*() const
{
return *get();
}
#if 0
// An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
// don't like this when |CharT| is a type without members.
pointer
operator->() const
{
return get();
}
#endif
nsWritingIterator<CharT>&
operator++()
{
++mPosition;
normalize_forward();
return *this;
}
nsWritingIterator<CharT>
operator++( int )
{
nsWritingIterator<CharT> result(*this);
++mPosition;
normalize_forward();
return result;
}
nsWritingIterator<CharT>&
operator--()
{
normalize_backward();
--mPosition;
return *this;
}
nsWritingIterator<CharT>
operator--( int )
{
nsWritingIterator<CharT> result(*this);
normalize_backward();
--mPosition;
return result;
}
const nsWritableFragment<CharT>&
fragment() const
{
return mFragment;
}
nsWritableFragment<CharT>&
fragment()
{
return mFragment;
}
const string_type&
string() const
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
string_type&
string()
{
NS_ASSERTION(mOwningString, "iterator not attached to a string (|mOwningString| == 0)");
return *mOwningString;
}
difference_type
size_forward() const
{
return mFragment.mEnd - mPosition;
}
difference_type
size_backward() const
{
return mPosition - mFragment.mStart;
}
nsWritingIterator<CharT>&
advance( difference_type n )
{
while ( n > 0 )
{
difference_type one_hop = NS_MIN(n, size_forward());
NS_ASSERTION(one_hop>0, "Infinite loop: can't advance a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
normalize_forward();
n -= one_hop;
}
while ( n < 0 )
{
normalize_backward();
difference_type one_hop = NS_MAX(n, -size_backward());
NS_ASSERTION(one_hop<0, "Infinite loop: can't advance (backward) a writing iterator beyond the end of a string");
// perhaps I should |break| if |!one_hop|?
mPosition += one_hop;
n -= one_hop;
}
return *this;
}
PRUint32
write( const value_type* s, PRUint32 n )
{
NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
n = NS_MIN(n, PRUint32(size_forward()));
nsCharTraits<value_type>::move(mPosition, s, n);
advance( difference_type(n) );
return n;
}
};
template <class CharT>
inline
void
nsReadingIterator<CharT>::normalize_forward()
{
while ( mPosition == mFragment.mEnd
&& mOwningString->GetReadableFragment(mFragment, kNextFragment) )
mPosition = mFragment.mStart;
}
template <class CharT>
inline
void
nsReadingIterator<CharT>::normalize_backward()
{
while ( mPosition == mFragment.mStart
&& mOwningString->GetReadableFragment(mFragment, kPrevFragment) )
mPosition = mFragment.mEnd;
}
template <class CharT>
inline
PRBool
operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
{
return lhs.get() == rhs.get();
}
template <class CharT>
inline
PRBool
operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
{
return lhs.get() != rhs.get();
}
//
// |nsWritingIterator|s
//
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_forward()
{
while ( mPosition == mFragment.mEnd
&& mOwningString->GetWritableFragment(mFragment, kNextFragment) )
mPosition = mFragment.mStart;
}
template <class CharT>
inline
void
nsWritingIterator<CharT>::normalize_backward()
{
while ( mPosition == mFragment.mStart
&& mOwningString->GetWritableFragment(mFragment, kPrevFragment) )
mPosition = mFragment.mEnd;
}
template <class CharT>
inline
PRBool
operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() == rhs.get();
}
template <class CharT>
inline
PRBool
operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
{
return lhs.get() != rhs.get();
}
#endif /* !defined(nsStringIterator_h___) */

View File

@@ -1,48 +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)
*/
#ifndef nsStringIteratorUtils_h___
#define nsStringIteratorUtils_h___
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
template <class Iterator>
inline
PRBool
SameFragment( const Iterator& lhs, const Iterator& rhs )
{
return lhs.fragment().mStart == rhs.fragment().mStart;
}
template <class CharT> class nsReadingIterator;
// NOTE: need to break iterators out into their own file (as with many classes here), need
// these routines, but can't currently |#include "nsReadableUtils.h"|, this hack is bad
// but we need it to get OS2 building again. Fix by splitting things into different files.
NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& );
NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& );
#endif /* !defined(nsStringIteratorUtils_h___) */

View File

@@ -1,76 +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)
*/
/* nsStringTraits.h --- declares specialized ``traits'' classes which allow templatized functions and classes to select appropriate non-template types */
#ifndef nsStringTraits_h___
#define nsStringTraits_h___
#ifndef nsStringFwd_h___
#include "nsStringFwd.h"
#endif
#ifndef nscore_h___
#include "nscore.h"
#endif
/**
*
*/
template <class CharT>
struct nsStringTraits
{
typedef nsAString abstract_string_type;
typedef nsAPromiseString abstract_promise_type;
typedef nsAFlatString abstract_flat_type;
typedef const nsDependentString literal_string_type;
};
#if 0
// for lame compilers, put these declarations into the general case
// so we only need to specialize for |char|
NS_SPECIALIZE_TEMPLATE
struct nsStringTraits<PRUnichar>
{
typedef nsAString abstract_string_type;
typedef nsAPromiseString abstract_promise_type;
typedef nsAFlatString abstract_flat_type;
typedef const nsDependentString literal_string_type;
};
#endif
NS_SPECIALIZE_TEMPLATE
struct nsStringTraits<char>
{
typedef nsACString abstract_string_type;
typedef nsAPromiseCString abstract_promise_type;
typedef nsAFlatCString abstract_flat_type;
typedef const nsDependentCString literal_string_type;
};
#endif /* !defined(nsStringTraits_h___) */

View File

@@ -1,251 +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)
*/
#ifndef nsXPIDLString_h___
#define nsXPIDLString_h___
#ifndef nsSharableString_h___
#include "nsSharableString.h"
#endif
#if DEBUG_STRING_STATS
#include <stdio.h>
#endif
/**
* |nsXPIDLC?String| extends |nsSharableC?String| with the ability
* to defer calculation of its length. This is crucial to allowing
* the |getter_Copies| assignment behavior.
*
* The mechanism relies on the fact that |GetSharedBufferHandle|
* must be called before any other object can share the buffer,
* and as the default implementation for |GetBufferHandle|, which is
* the operation on which all other flat string operations are based.
* A valid handle always contains a non-|NULL| data start and end.
* After use as an `out' string pointer parameter, an |nsXPIDLC?String|'s
* handle will have a non-|NULL| data start, but its data end will be
* |NULL|. This is the signal that the length needs to be recalculated.
* |GetSharedBufferHandle| detects this situation and repairs it.
*
* An |nsXPIDLC?String| is now a sharable object, just like |nsSharableC?String|.
* This simple implementation always allocates an intermediary handle
* object. This cost might turn out to be a burden, it's something we'll
* want to measure. A couple of optimizations spring to mind if allocation
* of the handle objects shows up on the performance radar:
* (1) introduce a custom allocator for the handles, e.g., keep free lists
* or arena allocate them, or (2) fatten up the |nsXPIDLC?String| with a
* local handle, and only allocate a shared handle in the event that
* someone actually wants to share. Both of these alternatives add
* complexity or space costs, and so we start with the simplest thing
* that could possibly work :-)
*/
class NS_COM nsXPIDLString
: public nsSharableString
{
public:
nsXPIDLString()
{
#if DEBUG_STRING_STATS
++sCreatedCount;
if ( ++sAliveCount > sHighWaterCount )
sHighWaterCount = sAliveCount;
#endif
}
nsXPIDLString( const nsXPIDLString& aString )
: nsSharableString(aString.GetSharedBufferHandle())
// copy-constructor required (or else C++ generates one for us)
{
#if DEBUG_STRING_STATS
++sCreatedCount;
if ( ++sAliveCount > sHighWaterCount )
sHighWaterCount = sAliveCount;
#endif
}
#if DEBUG_STRING_STATS
~nsXPIDLString()
{
--sAliveCount;
}
#endif
nsXPIDLString&
operator=( const nsXPIDLString& rhs )
// copy-assignment operator required (or else C++ generates one for us)
{
// self-assignment is handled by the underlying |nsAutoBufferHandle|
mBuffer = rhs.GetSharedBufferHandle();
return *this;
}
void Adopt( PRUnichar* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; }
// deprecated, to be eliminated
operator const PRUnichar*() const { return get(); }
PRUnichar operator[]( int i ) const { return get()[ i ]; }
class getter_Copies_t
{
public:
getter_Copies_t( nsXPIDLString& aString ) : mString(&aString) { }
// getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK
// getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK
operator PRUnichar**() const { return mString->PrepareForUseAsOutParam(); }
private:
nsXPIDLString* mString;
};
friend class getter_Copies_t;
protected:
#if DEBUG_STRING_STATS
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<PRUnichar>* GetBufferHandle() const;
#endif
virtual const nsSharedBufferHandle<PRUnichar>* GetSharedBufferHandle() const;
// overridden to fix the length after `out' parameter assignment, if necessary
PRUnichar** PrepareForUseAsOutParam();
#if DEBUG_STRING_STATS
static size_t sCreatedCount; // total number of |nsXPIDLString|s ever created
static size_t sAliveCount; // total number of |nsXPIDLStrings|s alive right now
static size_t sHighWaterCount; // greatest number of |nsXPIDLString|s alive at once
static size_t sAssignCount; // total number of times |nsXPIDLString|s were
// assigned into with |getter_Copies|
static size_t sShareCount; // total number times |nsXPIDLString|s were asked to share
public:
static void DebugPrintStats( FILE* );
#endif
};
inline
nsXPIDLString::getter_Copies_t
getter_Copies( nsXPIDLString& aString )
{
return nsXPIDLString::getter_Copies_t(aString);
}
class NS_COM nsXPIDLCString
: public nsSharableCString
{
public:
nsXPIDLCString()
{
#if DEBUG_STRING_STATS
++sCreatedCount;
if ( ++sAliveCount > sHighWaterCount )
sHighWaterCount = sAliveCount;
#endif
}
nsXPIDLCString( const nsXPIDLCString& aString )
: nsSharableCString(aString.GetSharedBufferHandle())
// copy-constructor required (or else C++ generates one for us)
{
#if DEBUG_STRING_STATS
++sCreatedCount;
if ( ++sAliveCount > sHighWaterCount )
sHighWaterCount = sAliveCount;
#endif
}
#if DEBUG_STRING_STATS
~nsXPIDLCString()
{
--sAliveCount;
}
#endif
nsXPIDLCString&
operator=( const nsXPIDLCString& rhs )
// copy-assignment operator required (or else C++ generates one for us)
{
// self-assignment is handled by the underlying |nsAutoBufferHandle|
mBuffer = rhs.GetSharedBufferHandle();
return *this;
}
void Adopt( char* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; }
// deprecated, to be eliminated
operator const char*() const { return get(); }
char operator[]( int i ) const { return get()[ i ]; }
class getter_Copies_t
{
public:
getter_Copies_t( nsXPIDLCString& aString ) : mString(&aString) { }
// getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK
// getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK
operator char**() const { return mString->PrepareForUseAsOutParam(); }
private:
nsXPIDLCString* mString;
};
friend class getter_Copies_t;
protected:
#if DEBUG_STRING_STATS
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const;
virtual const nsBufferHandle<char>* GetBufferHandle() const;
#endif
virtual const nsSharedBufferHandle<char>* GetSharedBufferHandle() const;
// overridden to fix the length after `out' parameter assignment, if necessary
char** PrepareForUseAsOutParam();
#if DEBUG_STRING_STATS
static size_t sCreatedCount; // total number of |nsXPIDLCString|s ever created
static size_t sAliveCount; // total number of |nsXPIDLCStrings|s alive right now
static size_t sHighWaterCount; // greatest number of |nsXPIDLCString|s alive at once
static size_t sAssignCount; // total number of times |nsXPIDLCString|s were
// assigned into with |getter_Copies|
static size_t sShareCount; // total number times |nsXPIDLCString|s were asked to share
public:
static void DebugPrintStats( FILE* );
#endif
};
inline
nsXPIDLCString::getter_Copies_t
getter_Copies( nsXPIDLCString& aString )
{
return nsXPIDLCString::getter_Copies_t(aString);
}
#endif /* !defined(nsXPIDLString_h___) */

View File

@@ -1,64 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
LIBRARY_NAME = string_s
REQUIRES = xpcom
CPPSRCS = \
nsAFlatString.cpp \
nsAString.cpp \
nsDependentConcatenation.cpp \
nsDependentString.cpp \
nsDependentSubstring.cpp \
nsFragmentedString.cpp \
nsPrintfCString.cpp \
nsPrivateSharableString.cpp \
nsPromiseFlatString.cpp \
nsReadableUtils.cpp \
nsSharableString.cpp \
nsSharedBufferList.cpp \
nsSlidingString.cpp \
nsXPIDLString.cpp \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
# Force use of PIC
FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_COM -D_IMPL_NS_BASE

View File

@@ -1,54 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
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)\nsDependentConcatenation.obj \
.\$(OBJDIR)\nsDependentString.obj \
.\$(OBJDIR)\nsDependentSubstring.obj \
.\$(OBJDIR)\nsFragmentedString.obj \
.\$(OBJDIR)\nsPrintfCString.obj \
.\$(OBJDIR)\nsPrivateSharableString.obj \
.\$(OBJDIR)\nsPromiseFlatString.obj \
.\$(OBJDIR)\nsReadableUtils.obj \
.\$(OBJDIR)\nsSharableString.obj \
.\$(OBJDIR)\nsSharedBufferList.obj \
.\$(OBJDIR)\nsSlidingString.obj \
.\$(OBJDIR)\nsXPIDLString.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,146 +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 "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;
}
}
PRUint32
nsAFlatString::Length() const
{
const nsBufferHandle<PRUnichar>* handle = GetBufferHandle();
return PRUint32(handle ? handle->DataLength() : 0);
}
PRUint32
nsAFlatCString::Length() const
{
const nsBufferHandle<char>* handle = GetBufferHandle();
return PRUint32(handle ? handle->DataLength() : 0);
}
const PRUnichar*
nsAFlatString::get() const
{
const nsBufferHandle<PRUnichar>* handle = GetBufferHandle();
// NS_ASSERTION(handle, "handle is null!");
return handle ? handle->DataStart() : 0;
}
const char*
nsAFlatCString::get() const
{
const nsBufferHandle<char>* handle = GetBufferHandle();
// NS_ASSERTION(handle, "handle is null!");
return handle ? handle->DataStart() : 0;
}

View File

@@ -1,948 +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 PRUnichar* lhs, const PRUnichar* rhs, PRUint32 aLength ) const
{
return nsCharTraits<PRUnichar>::compare(lhs, rhs, aLength);
}
int
nsCaseInsensitiveStringComparator::operator()( const PRUnichar* lhs, const PRUnichar* rhs, PRUint32 aLength ) const
{
return nsCRT::strncasecmp(lhs, rhs, aLength);
}
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;
}
PRBool
nsAString::Equals( const char_type* rhs ) const
{
return Equals(nsDependentString(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.IsDependentOn(*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(nsDependentString(aPtr));
}
void
nsAString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsDependentString(aPtr, aLength));
}
void
nsAString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsDependentString(&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.IsDependentOn(*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* aPtr )
{
do_AppendFromReadable(nsDependentString(aPtr));
}
void
nsAString::do_AppendFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AppendFromReadable(nsDependentString(aPtr, aLength));
}
void
nsAString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsDependentString(&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.IsDependentOn(*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(nsDependentString(aPtr), atPosition);
}
void
nsAString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsDependentString(aPtr, aLength), atPosition);
}
void
nsAString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsDependentString(&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.IsDependentOn(*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, nsDependentString(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)));
}
int
nsDefaultCStringComparator::operator()( const char* lhs, const char* rhs, PRUint32 aLength ) const
{
return nsCharTraits<char>::compare(lhs, rhs, aLength);
}
int
nsCaseInsensitiveCStringComparator::operator()( const char* lhs, const char* rhs, PRUint32 aLength ) const
{
return nsCRT::strncasecmp(lhs, rhs, aLength);
}
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;
}
PRBool
nsACString::Equals( const char_type* rhs ) const
{
return Equals(nsDependentCString(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.IsDependentOn(*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(nsDependentCString(aPtr));
}
void
nsACString::do_AssignFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AssignFromReadable(nsDependentCString(aPtr, aLength));
}
void
nsACString::do_AssignFromElement( char_type aChar )
{
do_AssignFromReadable(nsDependentCString(&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.IsDependentOn(*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* aPtr )
{
do_AppendFromReadable(nsDependentCString(aPtr));
}
void
nsACString::do_AppendFromElementPtrLength( const char_type* aPtr, size_type aLength )
{
do_AppendFromReadable(nsDependentCString(aPtr, aLength));
}
void
nsACString::do_AppendFromElement( char_type aChar )
{
do_AppendFromReadable(nsDependentCString(&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.IsDependentOn(*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(nsDependentCString(aPtr), atPosition);
}
void
nsACString::do_InsertFromElementPtrLength( const char_type* aPtr, index_type atPosition, size_type aLength )
{
do_InsertFromReadable(nsDependentCString(aPtr, aLength), atPosition);
}
void
nsACString::do_InsertFromElement( char_type aChar, index_type atPosition )
{
do_InsertFromReadable(nsDependentCString(&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.IsDependentOn(*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, nsDependentCString(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

@@ -1,202 +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)
*/
//-------1---------2---------3---------4---------5---------6---------7---------8
#include "nsAString.h"
// remember, no one should include "nsDependentConcatenation.h" themselves
// one always gets it through "nsAString.h"
#ifndef nsDependentConcatenation_h___
#include "nsDependentConcatenation.h"
#endif
PRUint32
nsDependentConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsDependentConcatenation::IsDependentOn( const string_type& aString ) const
{
return mStrings[0]->IsDependentOn(aString) || mStrings[1]->IsDependentOn(aString);
}
#if 0
PRBool
nsDependentConcatenation::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*
nsDependentConcatenation::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
nsDependentCConcatenation::Length() const
{
return mStrings[kLeftString]->Length() + mStrings[kRightString]->Length();
}
PRBool
nsDependentCConcatenation::IsDependentOn( const string_type& aString ) const
{
return mStrings[0]->IsDependentOn(aString) || mStrings[1]->IsDependentOn(aString);
}
#if 0
PRBool
nsDependentCConcatenation::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*
nsDependentCConcatenation::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

@@ -1,25 +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 "nsDependentString.h"

View File

@@ -1,123 +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 "nsDependentSubstring.h"
PRUint32
nsDependentSubstring::Length() const
{
return mLength;
}
const PRUnichar*
nsDependentSubstring::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
nsDependentCSubstring::Length() const
{
return mLength;
}
const char*
nsDependentCSubstring::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

@@ -1,162 +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 XPCOM.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*/
#include "nsFragmentedString.h"
const PRUnichar*
nsFragmentedString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
const nsSharedBufferList::Buffer* buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
break;
case kFirstFragment:
buffer = mBufferList.GetFirstBuffer();
break;
case kLastFragment:
buffer = mBufferList.GetLastBuffer();
break;
case kNextFragment:
buffer = NS_STATIC_CAST(const nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
break;
case kFragmentAt:
// ...work...
break;
}
if ( buffer )
{
aFragment.mStart = buffer->DataStart();
aFragment.mEnd = buffer->DataEnd();
aFragment.mFragmentIdentifier = buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
PRUnichar*
nsFragmentedString::GetWritableFragment( nsWritableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
{
nsSharedBufferList::Buffer* buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mPrev;
break;
case kFirstFragment:
buffer = mBufferList.GetFirstBuffer();
break;
case kLastFragment:
buffer = mBufferList.GetLastBuffer();
break;
case kNextFragment:
buffer = NS_STATIC_CAST(nsSharedBufferList::Buffer*, aFragment.mFragmentIdentifier)->mNext;
break;
case kFragmentAt:
// ...work...
break;
}
if ( buffer )
{
aFragment.mStart = buffer->DataStart();
aFragment.mEnd = buffer->DataEnd();
aFragment.mFragmentIdentifier = buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
/**
* ...
*/
PRUint32
nsFragmentedString::Length() const
{
return PRUint32(mBufferList.GetDataLength());
}
/**
* |SetLength|
*/
void
nsFragmentedString::SetLength( PRUint32 aNewLength )
{
// according to the current interpretation of |SetLength|,
// cut off characters from the end, or else add unitialized space to fill
if ( aNewLength < PRUint32(mBufferList.GetDataLength()) )
{
// if ( aNewLength )
mBufferList.DiscardSuffix(mBufferList.GetDataLength()-aNewLength);
// else
// mBufferList.DestroyBuffers();
}
// temporarily... eliminate as soon as our munging routines don't need this form of |SetLength|
else if ( aNewLength > PRUint32(mBufferList.GetDataLength()) )
{
size_t empty_space_to_add = aNewLength - mBufferList.GetDataLength();
nsSharedBufferList::Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(0, 0, empty_space_to_add);
new_buffer->DataEnd(new_buffer->DataStart()+empty_space_to_add);
mBufferList.LinkBuffer(mBufferList.GetLastBuffer(), new_buffer, 0);
}
}
#if 0
/**
* |SetCapacity|.
*
* If a client tries to increase the capacity of multi-fragment string, perhaps a single
* empty fragment of the appropriate size should be appended.
*/
void
nsFragmentedString::SetCapacity( PRUint32 aNewCapacity )
{
if ( !aNewCapacity )
{
// |SetCapacity(0)| is special and means ``release all storage''.
}
else if ( aNewCapacity > ... )
{
}
}
#endif

View File

@@ -1,25 +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 "nsLocalString.h"

View File

@@ -1,135 +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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author:
* Scott Collins <scc@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "nsPrintfCString.h"
#include <stdarg.h>
#include "prprf.h"
nsPrintfCString::nsPrintfCString( const char* format, ... )
: mStart(mLocalBuffer),
mLength(0)
{
va_list ap;
size_t logical_capacity = kLocalBufferSize;
size_t physical_capacity = logical_capacity + 1;
va_start(ap, format);
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
va_end(ap);
}
nsPrintfCString::nsPrintfCString( size_t n, const char* format, ... )
: mStart(mLocalBuffer),
mLength(0)
{
va_list ap;
// make sure there's at least |n| space
size_t logical_capacity = kLocalBufferSize;
if ( n > logical_capacity )
{
char* nonlocal_buffer = new char[n];
// if we got something, use it
if ( nonlocal_buffer )
{
mStart = nonlocal_buffer;
logical_capacity = n;
}
// else, it's the error case ... we'll use what space we have
// (since we can't throw)
}
size_t physical_capacity = logical_capacity + 1;
va_start(ap, format);
mLength = PR_vsnprintf(mStart, physical_capacity, format, ap);
va_end(ap);
}
nsPrintfCString::~nsPrintfCString()
{
if ( mStart != mLocalBuffer )
delete [] mStart;
}
PRUint32
nsPrintfCString::Length() const
{
return mLength;
}
#if 0
PRBool
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
aFragment.mFragmentIdentifier = this;
// fall through
case kThisFragment:
aFragment.mStart = mStart;
aFragment.mEnd = mStart + mLength;
return PR_TRUE;
default:
return PR_FALSE;
}
}
#else
const char*
nsPrintfCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
switch ( aRequest )
{
case kFirstFragment:
case kLastFragment:
case kFragmentAt:
aFragment.mEnd = (aFragment.mStart = mStart) + mLength;
return mStart + aOffset;
case kPrevFragment:
case kNextFragment:
default:
return 0;
}
}
#endif

View File

@@ -1,85 +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 "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

@@ -1,197 +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)
*/
//-------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

@@ -1,151 +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 "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 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();
}
PRBool
nsPromiseFlatString::IsDependentOn( const nsAString& aString ) const
{
return mPromisedString->IsDependentOn(aString);
}
const PRUnichar*
nsPromiseFlatString::get() const
{
return mPromisedString->get();
}
PRUint32
nsPromiseFlatString::Length() const
{
return mPromisedString->Length();
}
const PRUnichar*
nsPromiseFlatString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
return mPromisedString->GetReadableFragment(aFragment, aRequest, aOffset);
}
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 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();
}
PRBool
nsPromiseFlatCString::IsDependentOn( const nsACString& aString ) const
{
return mPromisedString->IsDependentOn(aString);
}
const char*
nsPromiseFlatCString::get() const
{
return mPromisedString->get();
}
PRUint32
nsPromiseFlatCString::Length() const
{
return mPromisedString->Length();
}
const char*
nsPromiseFlatCString::GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
return mPromisedString->GetReadableFragment(aFragment, aRequest, aOffset);
}

View File

@@ -1,123 +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 "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

@@ -1,865 +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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*/
#include "nsReadableUtils.h"
#include "nsMemory.h"
#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
* to their own file
*/
template <class CharT>
class XPCOM_StringAllocator
: public nsStringAllocator<CharT>
{
public:
virtual void Deallocate( CharT* ) const;
};
template <class CharT>
void
XPCOM_StringAllocator<CharT>::Deallocate( CharT* aBuffer ) const
{
nsMemory::Free(aBuffer);
}
NS_COM
nsStringAllocator<char>&
StringAllocator_char()
{
static XPCOM_StringAllocator<char> sStringAllocator_char;
return sStringAllocator_char;
}
NS_COM
nsStringAllocator<PRUnichar>&
StringAllocator_wchar_t()
{
static XPCOM_StringAllocator<PRUnichar> sStringAllocator_wchar_t;
return sStringAllocator_wchar_t;
}
template <class CharT> class CalculateLength
{
public:
typedef CharT value_type;
CalculateLength() : mDistance(0) { }
size_t GetDistance() const { return mDistance; }
PRUint32 write( const CharT*, PRUint32 N )
{ mDistance += N; return N; }
private:
size_t mDistance;
};
template <class CharT>
inline
size_t
Distance_Impl( const nsReadingIterator<CharT>& aStart,
const nsReadingIterator<CharT>& aEnd )
{
CalculateLength<CharT> sink;
nsReadingIterator<CharT> fromBegin(aStart);
copy_string(fromBegin, aEnd, sink);
return sink.GetDistance();
}
NS_COM
size_t
Distance( const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
return Distance_Impl(aStart, aEnd);
}
NS_COM
size_t
Distance( const nsReadingIterator<char>& aStart, const nsReadingIterator<char>& aEnd )
{
return Distance_Impl(aStart, aEnd);
}
/**
* A character sink that performs a |reinterpret_cast| style conversion between character types.
*/
template <class FromCharT, class ToCharT>
class LossyConvertEncoding
{
public:
typedef FromCharT value_type;
typedef FromCharT input_type;
typedef ToCharT output_type;
public:
LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { }
PRUint32
write( const input_type* aSource, PRUint32 aSourceLength )
{
const input_type* done_writing = aSource + aSourceLength;
while ( aSource < done_writing )
*mDestination++ = (output_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior
return aSourceLength;
}
void
write_terminator()
{
*mDestination = output_type(0);
}
private:
output_type* mDestination;
};
NS_COM
void
CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
nsWritingIterator<char> toBegin;
LossyConvertEncoding<PRUnichar, char> converter(aDest.BeginWriting(toBegin).get());
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
}
NS_COM
void
CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest )
{
// right now, this won't work on multi-fragment destinations
aDest.SetLength(aSource.Length());
nsReadingIterator<char> fromBegin, fromEnd;
nsWritingIterator<PRUnichar> toBegin;
LossyConvertEncoding<char, PRUnichar> converter(aDest.BeginWriting(toBegin).get());
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
}
/**
* A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
*
* @param aSource an string you will eventually be making a copy of
* @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
*
*/
template <class FromStringT, class ToCharT>
inline
ToCharT*
AllocateStringCopy( const FromStringT& aSource, ToCharT* )
{
return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
}
NS_COM
char*
ToNewCString( const nsAString& aSource )
{
char* result = AllocateStringCopy(aSource, (char*)0);
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
LossyConvertEncoding<PRUnichar, char> converter(result);
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
return result;
}
NS_COM
char*
ToNewUTF8String( const nsAString& aSource )
{
NS_ConvertUCS2toUTF8 temp(aSource);
char* result;
if (temp.mOwnsBuffer) {
// We allocated. Trick the string into not freeing its buffer to
// avoid an extra allocation.
result = temp.mStr;
temp.mStr=0;
temp.mOwnsBuffer = PR_FALSE;
}
else {
// We didn't allocate a buffer, so we need to copy it out of the
// nsCAutoString's storage.
result = nsCRT::strdup(temp.mStr);
}
return result;
}
NS_COM
char*
ToNewCString( const nsACString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
char* result = AllocateStringCopy(aSource, (char*)0);
nsReadingIterator<char> fromBegin, fromEnd;
char* toBegin = result;
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0);
return result;
}
NS_COM
PRUnichar*
ToNewUnicode( const nsAString& aSource )
{
// no conversion needed, just allocate a buffer of the correct length and copy into it
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = result;
*copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0);
return result;
}
NS_COM
PRUnichar*
ToNewUnicode( const nsACString& aSource )
{
PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
nsReadingIterator<char> fromBegin, fromEnd;
LossyConvertEncoding<char, PRUnichar> converter(result);
copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
return result;
}
NS_COM
PRUnichar*
CopyUnicodeTo( const nsAString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength )
{
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = aDest;
copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin);
return aDest;
}
NS_COM
void
CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest )
{
nsWritingIterator<PRUnichar> writer;
aDest.SetLength(Distance(aSrcStart, aSrcEnd));
aDest.BeginWriting(writer);
nsReadingIterator<PRUnichar> fromBegin(aSrcStart);
copy_string(fromBegin, aSrcEnd, writer);
}
NS_COM
void
AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart,
const nsReadingIterator<PRUnichar>& aSrcEnd,
nsAString& aDest )
{
nsWritingIterator<PRUnichar> writer;
PRUint32 oldLength = aDest.Length();
aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd));
aDest.BeginWriting(writer).advance(oldLength);
nsReadingIterator<PRUnichar> fromBegin(aSrcStart);
copy_string(fromBegin, aSrcEnd, writer);
}
NS_COM
PRBool
IsASCII( const nsAString& aString )
{
static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
// Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
nsReadingIterator<PRUnichar> done_reading;
aString.EndReading(done_reading);
// for each chunk of |aString|...
PRUint32 fragmentLength = 0;
nsReadingIterator<PRUnichar> iter;
for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
{
fragmentLength = PRUint32(iter.size_forward());
const PRUnichar* c = iter.get();
const PRUnichar* fragmentEnd = c + fragmentLength;
// for each character in this chunk...
while ( c < fragmentEnd )
if ( *c++ & NOT_ASCII )
return PR_FALSE;
}
return PR_TRUE;
}
/**
* A character sink for case conversion.
*/
template <class CharT>
class ConvertToUpperCase
{
public:
typedef CharT value_type;
PRUint32
write( const CharT* aSource, PRUint32 aSourceLength )
{
for ( PRUint32 i=0; i<aSourceLength; ++i )
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToUpper(aSource[i]);
return aSourceLength;
}
};
NS_COM
void
ToUpperCase( nsAString& aString )
{
nsAString::iterator fromBegin, fromEnd;
ConvertToUpperCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToUpperCase( nsACString& aCString )
{
nsACString::iterator fromBegin, fromEnd;
ConvertToUpperCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}
/**
* A character sink for case conversion.
*/
template <class CharT>
class ConvertToLowerCase
{
public:
typedef CharT value_type;
PRUint32
write( const CharT* aSource, PRUint32 aSourceLength )
{
for ( PRUint32 i=0; i<aSourceLength; ++i )
NS_CONST_CAST(CharT*, aSource)[i] = nsCRT::ToLower(aSource[i]);
return aSourceLength;
}
};
NS_COM
void
ToLowerCase( nsAString& aString )
{
nsAString::iterator fromBegin, fromEnd;
ConvertToLowerCase<PRUnichar> converter;
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
}
NS_COM
void
ToLowerCase( nsACString& aCString )
{
nsACString::iterator fromBegin, fromEnd;
ConvertToLowerCase<char> converter;
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
}
template <class StringT, class IteratorT, class Comparator>
PRBool
FindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd, const Comparator& compare )
{
PRBool found_it = PR_FALSE;
// only bother searching at all if we're given a non-empty range to search
if ( aSearchStart != aSearchEnd )
{
IteratorT aPatternStart, aPatternEnd;
aPattern.BeginReading(aPatternStart);
aPattern.EndReading(aPatternEnd);
// outer loop keeps searching till we find it or run out of string to search
while ( !found_it )
{
// fast inner loop (that's what it's called, not what it is) looks for a potential match
while ( aSearchStart != aSearchEnd && !compare(*aPatternStart, *aSearchStart) )
++aSearchStart;
// if we broke out of the `fast' loop because we're out of string ... we're done: no match
if ( aSearchStart == aSearchEnd )
break;
// otherwise, we're at a potential match, let's see if we really hit one
IteratorT testPattern(aPatternStart);
IteratorT testSearch(aSearchStart);
// slow inner loop verifies the potential match (found by the `fast' loop) at the current position
for(;;)
{
// we already compared the first character in the outer loop,
// so we'll advance before the next comparison
++testPattern;
++testSearch;
// if we verified all the way to the end of the pattern, then we found it!
if ( testPattern == aPatternEnd )
{
found_it = PR_TRUE;
aSearchEnd = testSearch; // return the exact found range through the parameters
break;
}
// if we got to end of the string we're searching before we hit the end of the
// pattern, we'll never find what we're looking for
if ( testSearch == aSearchEnd )
{
aSearchStart = aSearchEnd;
break;
}
// else if we mismatched ... it's time to advance to the next search position
// and get back into the `fast' loop
if ( !compare(*testPattern, *testSearch) )
{
++aSearchStart;
break;
}
}
}
}
return found_it;
}
class CaseSensitivePRUnicharComparator
{
public:
PRBool operator()( PRUnichar lhs, PRUnichar rhs ) const { return lhs == rhs; }
};
class CaseSensitiveCharComparator
{
public:
PRBool operator()( char lhs, char rhs ) const { return lhs == rhs; }
};
class CaseInsensitivePRUnicharComparator
{
public:
PRBool operator()( PRUnichar lhs, PRUnichar rhs ) const { return nsCRT::ToUpper(lhs) == nsCRT::ToUpper(rhs); }
};
class CaseInsensitiveCharComparator
{
public:
PRBool operator()( char lhs, char rhs ) const { return nsCRT::ToUpper(lhs) == nsCRT::ToUpper(rhs); }
};
NS_COM
PRBool
FindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, CaseSensitivePRUnicharComparator());
}
NS_COM
PRBool
FindInReadable( const nsACString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, CaseSensitiveCharComparator());
}
NS_COM
PRBool
CaseInsensitiveFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, CaseInsensitivePRUnicharComparator());
}
NS_COM
PRBool
CaseInsensitiveFindInReadable( const nsACString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
{
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, CaseInsensitiveCharComparator());
}
/**
* This implementation is simple, but does too much work.
* It searches the entire string from left to right, and returns the last match found, if any.
* This implementation will be replaced when I get |reverse_iterator|s working.
*/
NS_COM
PRBool
RFindInReadable( const nsAString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
{
PRBool found_it = PR_FALSE;
nsReadingIterator<PRUnichar> savedSearchEnd(aSearchEnd);
nsReadingIterator<PRUnichar> searchStart(aSearchStart), searchEnd(aSearchEnd);
while ( searchStart != searchEnd )
{
if ( FindInReadable(aPattern, searchStart, searchEnd) )
{
found_it = PR_TRUE;
// this is the best match so far, so remember it
aSearchStart = searchStart;
aSearchEnd = searchEnd;
// ...and get ready to search some more
// (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
++searchStart;
searchEnd = savedSearchEnd;
}
}
// if we never found it, return an empty range
if ( !found_it )
aSearchStart = aSearchEnd;
return found_it;
}
NS_COM
PRBool
RFindInReadable( const nsACString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
{
PRBool found_it = PR_FALSE;
nsReadingIterator<char> savedSearchEnd(aSearchEnd);
nsReadingIterator<char> searchStart(aSearchStart), searchEnd(aSearchEnd);
while ( searchStart != searchEnd )
{
if ( FindInReadable(aPattern, searchStart, searchEnd) )
{
found_it = PR_TRUE;
// this is the best match so far, so remember it
aSearchStart = searchStart;
aSearchEnd = searchEnd;
// ...and get ready to search some more
// (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
++searchStart;
searchEnd = savedSearchEnd;
}
}
// if we never found it, return an empty range
if ( !found_it )
aSearchStart = aSearchEnd;
return found_it;
}
PRBool
nsSubstituteString::IsDependentOn( const nsAString& aString ) const
{
return mText.IsDependentOn(aString) || mPattern.IsDependentOn(aString) || mReplacement.IsDependentOn(aString);
}
PRUint32
nsSubstituteString::MaxLength() const
{
PRInt32 numberOfMatches = mNumberOfMatches;
// if we don't know exactly how long the result will be,
// calculate the longest possible result
if ( numberOfMatches < 0 )
{
if ( mReplacement.Length() <= mPattern.Length() )
numberOfMatches = 0; // substitutions shrink the result, so worst case is none
else
numberOfMatches = PRInt32(mText.Length() / mPattern.Length());
// substitutions grow the result, so worst case is the maximum number of times |mPattern| can be found
}
PRInt32 costPerMatch = PRInt32(mReplacement.Length()) - PRInt32(mPattern.Length());
return mText.Length() + (numberOfMatches * costPerMatch);
}
void
nsSubstituteString::CountMatches() const
{
nsReadingIterator<PRUnichar> textEnd;
nsReadingIterator<PRUnichar> searchEnd = mText.EndReading(textEnd);
nsReadingIterator<PRUnichar> searchStart;
mText.BeginReading(searchStart);
PRInt32 numberOfMatches = 0;
while ( FindInReadable(mPattern, searchStart, searchEnd) )
{
++numberOfMatches;
searchStart = searchEnd;
searchEnd = textEnd;
}
NS_CONST_CAST(nsSubstituteString*, this)->mNumberOfMatches = numberOfMatches;
}
PRUint32
nsSubstituteString::Length() const
{
if ( mNumberOfMatches < 0 )
CountMatches();
return MaxLength();
}
PRUnichar*
nsSubstituteString::operator()( PRUnichar* aDestBuffer ) const
{
nsReadingIterator<PRUnichar> replacementEnd;
mReplacement.EndReading(replacementEnd);
nsReadingIterator<PRUnichar> textEnd;
nsReadingIterator<PRUnichar> searchEnd = mText.EndReading(textEnd);
nsReadingIterator<PRUnichar> uncopiedStart;
nsReadingIterator<PRUnichar> searchStart = mText.BeginReading(uncopiedStart);
while ( FindInReadable(mPattern, searchStart, searchEnd) )
{
// |searchStart| and |searchEnd| now bracket the match
// copy everything up to this match
copy_string(uncopiedStart, searchStart, aDestBuffer); // updates |aDestBuffer|
// copy the replacement
nsReadingIterator<PRUnichar> replacementStart;
copy_string(mReplacement.BeginReading(replacementStart), replacementEnd, aDestBuffer);
// start searching from where the current match ends
uncopiedStart = searchStart = searchEnd;
searchEnd = textEnd;
}
// copy everything after the final (if any) match
copy_string(uncopiedStart, textEnd, aDestBuffer);
return aDestBuffer;
}
PRBool
nsSubstituteCString::IsDependentOn( const nsACString& aString ) const
{
return mText.IsDependentOn(aString) || mPattern.IsDependentOn(aString) || mReplacement.IsDependentOn(aString);
}
PRUint32
nsSubstituteCString::MaxLength() const
{
PRInt32 numberOfMatches = mNumberOfMatches;
// if we don't know exactly how long the result will be,
// calculate the longest possible result
if ( numberOfMatches < 0 )
{
if ( mReplacement.Length() <= mPattern.Length() )
numberOfMatches = 0; // substitutions shrink the result, so worst case is none
else
numberOfMatches = PRInt32(mText.Length() / mPattern.Length());
// substitutions grow the result, so worst case is the maximum number of times |mPattern| can be found
}
PRInt32 costPerMatch = PRInt32(mReplacement.Length()) - PRInt32(mPattern.Length());
return mText.Length() + (numberOfMatches * costPerMatch);
}
void
nsSubstituteCString::CountMatches() const
{
nsReadingIterator<char> textEnd;
nsReadingIterator<char> searchEnd = mText.EndReading(textEnd);
nsReadingIterator<char> searchStart;
mText.BeginReading(searchStart);
PRInt32 numberOfMatches = 0;
while ( FindInReadable(mPattern, searchStart, searchEnd) )
{
++numberOfMatches;
searchStart = searchEnd;
searchEnd = textEnd;
}
NS_CONST_CAST(nsSubstituteCString*, this)->mNumberOfMatches = numberOfMatches;
}
PRUint32
nsSubstituteCString::Length() const
{
if ( mNumberOfMatches < 0 )
CountMatches();
return MaxLength();
}
char*
nsSubstituteCString::operator()( char* aDestBuffer ) const
{
nsReadingIterator<char> replacementEnd;
mReplacement.EndReading(replacementEnd);
nsReadingIterator<char> textEnd;
nsReadingIterator<char> searchEnd = mText.EndReading(textEnd);
nsReadingIterator<char> uncopiedStart;
nsReadingIterator<char> searchStart = mText.BeginReading(uncopiedStart);
while ( FindInReadable(mPattern, searchStart, searchEnd) )
{
// |searchStart| and |searchEnd| now bracket the match
// copy everything up to this match
copy_string(uncopiedStart, searchStart, aDestBuffer); // updates |aDestBuffer|
// copy the replacement
nsReadingIterator<char> replacementStart;
copy_string(mReplacement.BeginReading(replacementStart), replacementEnd, aDestBuffer);
// start searching from where the current match ends
uncopiedStart = searchStart = searchEnd;
searchEnd = textEnd;
}
// copy everything after the final (if any) match
copy_string(uncopiedStart, textEnd, aDestBuffer);
return aDestBuffer;
}
NS_COM
PRBool
FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, const nsReadingIterator<PRUnichar>& aSearchEnd )
{
while ( aSearchStart != aSearchEnd )
{
PRInt32 fragmentLength;
if ( SameFragment(aSearchStart, aSearchEnd) )
fragmentLength = aSearchEnd.get() - aSearchStart.get();
else
fragmentLength = aSearchStart.size_forward();
const PRUnichar* charFoundAt = nsCharTraits<PRUnichar>::find(aSearchStart.get(), fragmentLength, aChar);
if ( charFoundAt ) {
aSearchStart.advance( charFoundAt - aSearchStart.get() );
return PR_TRUE;
}
aSearchStart.advance(fragmentLength);
}
return PR_FALSE;
}
NS_COM
PRBool
FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, const nsReadingIterator<char>& aSearchEnd )
{
while ( aSearchStart != aSearchEnd )
{
PRInt32 fragmentLength;
if ( SameFragment(aSearchStart, aSearchEnd) )
fragmentLength = aSearchEnd.get() - aSearchStart.get();
else
fragmentLength = aSearchStart.size_forward();
const char* charFoundAt = nsCharTraits<char>::find(aSearchStart.get(), fragmentLength, aChar);
if ( charFoundAt ) {
aSearchStart.advance( charFoundAt - aSearchStart.get() );
return PR_TRUE;
}
aSearchStart.advance(fragmentLength);
}
return PR_FALSE;
}
NS_COM
PRUint32
CountCharInReadable( const nsAString& aStr,
PRUnichar aChar )
{
PRUint32 count = 0;
nsReadingIterator<PRUnichar> begin, end;
aStr.BeginReading(begin);
aStr.EndReading(end);
while (begin != end) {
if (*begin == aChar) {
++count;
}
++begin;
}
return count;
}
NS_COM
PRUint32
CountCharInReadable( const nsACString& aStr,
char aChar )
{
PRUint32 count = 0;
nsReadingIterator<char> begin, end;
aStr.BeginReading(begin);
aStr.EndReading(end);
while (begin != end) {
if (*begin == aChar) {
++count;
}
++begin;
}
return count;
}

View File

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

View File

@@ -1,184 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#include "nsSharedBufferList.h"
#ifndef nsAlgorithm_h___
#include "nsAlgorithm.h"
// for |copy_string|
#endif
ptrdiff_t
nsSharedBufferList::Position::Distance( const Position& aStart, const Position& aEnd )
{
ptrdiff_t result = 0;
if ( aStart.mBuffer == aEnd.mBuffer )
result = aEnd.mPosInBuffer - aStart.mPosInBuffer;
else
{
result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer;
for ( Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext )
result += b->DataLength();
result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart();
}
return result;
}
void
nsSharedBufferList::DestroyBuffers()
{
// destroy the entire list of buffers, without bothering to manage their links
Buffer* next_buffer;
for ( Buffer* cur_buffer=mFirstBuffer; cur_buffer; cur_buffer=next_buffer )
{
next_buffer = cur_buffer->mNext;
operator delete(cur_buffer);
}
mFirstBuffer = mLastBuffer = 0;
mTotalDataLength = 0;
}
nsSharedBufferList::~nsSharedBufferList()
{
DestroyBuffers();
}
void
nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer )
{
NS_ASSERTION(aNewBuffer, "aNewBuffer");
NS_ASSERTION(aPrevBuffer || mFirstBuffer == aNextBuffer, "aPrevBuffer || mFirstBuffer == aNextBuffer");
NS_ASSERTION(!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer, "!aPrevBuffer || aPrevBuffer->mNext == aNextBuffer");
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
if ( (aNewBuffer->mPrev = aPrevBuffer) )
aPrevBuffer->mNext = aNewBuffer;
else
mFirstBuffer = aNewBuffer;
if ( (aNewBuffer->mNext = aNextBuffer) )
aNextBuffer->mPrev = aNewBuffer;
else
mLastBuffer = aNewBuffer;
mTotalDataLength += aNewBuffer->DataLength();
}
void
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition, SplitDisposition aSplitDirection )
{
Buffer* bufferToSplit = aSplitPosition.mBuffer;
NS_ASSERTION(bufferToSplit, "bufferToSplit");
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
// if the caller specifically asked to split off the right side of the buffer-to-be-split
// or else if they asked for the minimum amount of work, and that turned out to be the right side...
ptrdiff_t savedLength = mTotalDataLength;
if ( aSplitDirection==kSplitCopyRightData ||
( aSplitDirection==kSplitCopyLeastData && ((bufferToSplit->DataLength() >> 1) <= splitOffset) ) )
{
// ...then allocate a new buffer initializing it by copying all the data _after_ the split in the source buffer (i.e., `split right')
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
}
else
{
// ...else move the data _before_ the split point (i.e., `split left')
Buffer* new_buffer = NewSingleAllocationBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
}
mTotalDataLength = savedLength;
// duh! splitting a buffer doesn't change the length.
}
nsSharedBufferList::Buffer*
nsSharedBufferList::UnlinkBuffer( Buffer* aBufferToUnlink )
{
NS_ASSERTION(aBufferToUnlink, "aBufferToUnlink");
Buffer* prev_buffer = aBufferToUnlink->mPrev;
Buffer* next_buffer = aBufferToUnlink->mNext;
if ( prev_buffer )
prev_buffer->mNext = next_buffer;
else
mFirstBuffer = next_buffer;
if ( next_buffer )
next_buffer->mPrev = prev_buffer;
else
mLastBuffer = prev_buffer;
mTotalDataLength -= aBufferToUnlink->DataLength();
return aBufferToUnlink;
}
void
nsSharedBufferList::DiscardSuffix( PRUint32 /* aLengthToDiscard */ )
{
// XXX
}
#if 0
template <class CharT>
void
nsChunkList<CharT>::CutTrailingData( PRUint32 aLengthToCut )
{
Chunk* chunk = mLastChunk;
while ( chunk && aLengthToCut )
{
Chunk* prev_chunk = chunk->mPrev;
if ( aLengthToCut < chunk->mDataLength )
{
chunk->mDataLength -= aLengthToCut;
aLengthToCut = 0;
}
else
{
RemoveChunk(chunk);
aLengthToCut -= chunk->mDataLength;
operator delete(chunk);
}
chunk = prev_chunk;
}
}
#endif

View File

@@ -1,338 +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 strings.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Collins <scc@mozilla.org> (original author)
*
*/
#include "nsSlidingString.h"
#ifndef nsBufferHandleUtils_h___
#include "nsBufferHandleUtils.h"
#endif
#include <new.h>
/**
* |nsSlidingSharedBufferList|
*/
void
nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer )
{
if ( aRecentlyReleasedBuffer == mFirstBuffer )
{
while ( mFirstBuffer && !mFirstBuffer->IsReferenced() )
delete UnlinkBuffer(mFirstBuffer);
}
}
/**
* |nsSlidingSubstring|
*/
// copy constructor
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString )
: mStart(aString.mStart),
mEnd(aString.mEnd),
mBufferList(aString.mBufferList),
mLength(aString.mLength)
{
acquire_ownership_of_buffer_list();
}
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
: mStart(aStart),
mEnd(aEnd),
mBufferList(aString.mBufferList),
mLength(PRUint32(Position::Distance(mStart, mEnd)))
{
acquire_ownership_of_buffer_list();
}
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString )
: mStart(aString.mStart),
mEnd(aString.mEnd),
mBufferList(aString.mBufferList),
mLength(aString.mLength)
{
acquire_ownership_of_buffer_list();
}
nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
: mStart(aStart),
mEnd(aEnd),
mBufferList(aString.mBufferList),
mLength(PRUint32(Position::Distance(mStart, mEnd)))
{
acquire_ownership_of_buffer_list();
}
nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList )
: mBufferList(aBufferList)
{
init_range_from_buffer_list();
acquire_ownership_of_buffer_list();
}
typedef const nsSharedBufferList::Buffer* Buffer_ptr;
static nsSharedBufferList::Buffer*
AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAString& aDataSource )
{
typedef const PRUnichar* PRUnichar_ptr;
// figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part
size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, PRUnichar_ptr(0));
// figure out how many |CharT|s wee need to fit in the data part
size_t string_length = aDataSource.Length();
// how many bytes is that (including a zero-terminator so we can claim to be flat)?
size_t string_size = (string_length+1) * sizeof(PRUnichar);
nsSharedBufferList::Buffer* result = 0;
void* handle_ptr = ::operator new(handle_size + string_size);
if ( handle_ptr )
{
typedef PRUnichar* PRUnichar_ptr;
PRUnichar* string_start_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size);
PRUnichar* string_end_ptr = string_start_ptr + string_length;
nsReadingIterator<PRUnichar> fromBegin, fromEnd;
PRUnichar* toBegin = string_start_ptr;
copy_string(aDataSource.BeginReading(fromBegin), aDataSource.EndReading(fromEnd), toBegin);
result = new (handle_ptr) nsSharedBufferList::Buffer(string_start_ptr, string_end_ptr, string_start_ptr, string_end_ptr+1, PR_TRUE);
}
return result;
}
nsSlidingSubstring::nsSlidingSubstring( const nsAString& aSourceString )
: mBufferList(new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString)))
{
init_range_from_buffer_list();
acquire_ownership_of_buffer_list();
}
void
nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString )
{
aString.acquire_ownership_of_buffer_list();
release_ownership_of_buffer_list();
mStart = aString.mStart;
mEnd = aString.mEnd;
mBufferList = aString.mBufferList;
mLength = aString.mLength;
}
void
nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
release_ownership_of_buffer_list();
mStart = aStart;
mEnd = aEnd;
mBufferList = aString.mBufferList;
mLength = PRUint32(Position::Distance(mStart, mEnd));
acquire_ownership_of_buffer_list();
}
void
nsSlidingSubstring::Rebind( const nsSlidingString& aString )
{
aString.acquire_ownership_of_buffer_list();
release_ownership_of_buffer_list();
mStart = aString.mStart;
mEnd = aString.mEnd;
mBufferList = aString.mBufferList;
mLength = aString.mLength;
}
void
nsSlidingSubstring::Rebind( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd )
{
release_ownership_of_buffer_list();
mStart = aStart;
mEnd = aEnd;
mBufferList = aString.mBufferList;
mLength = PRUint32(Position::Distance(mStart, mEnd));
acquire_ownership_of_buffer_list();
}
void
nsSlidingSubstring::Rebind( const nsAString& aSourceString )
{
release_ownership_of_buffer_list();
mBufferList = new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString));
init_range_from_buffer_list();
acquire_ownership_of_buffer_list();
}
nsSlidingSubstring::~nsSlidingSubstring()
{
release_ownership_of_buffer_list();
}
const PRUnichar*
nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
const Buffer* result_buffer = 0;
switch ( aRequest )
{
case kPrevFragment:
{
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
if ( current_buffer != mStart.mBuffer )
result_buffer = current_buffer->mPrev;
}
break;
case kFirstFragment:
result_buffer = mStart.mBuffer;
break;
case kLastFragment:
result_buffer = mEnd.mBuffer;
break;
case kNextFragment:
{
const Buffer* current_buffer = NS_STATIC_CAST(const Buffer*, aFragment.mFragmentIdentifier);
if ( current_buffer != mEnd.mBuffer )
result_buffer = current_buffer->mNext;
}
break;
case kFragmentAt:
{
// kFragmentAt is going away; we hate this linear search
PRUint32 N;
result_buffer = mStart.mBuffer;
while ( result_buffer && (N = PRUint32(result_buffer->DataLength())) < aOffset )
{
aOffset -= N;
result_buffer = result_buffer->mNext;
}
}
break;
}
if ( result_buffer )
{
if ( result_buffer == mStart.mBuffer )
aFragment.mStart = mStart.mPosInBuffer;
else
aFragment.mStart = result_buffer->DataStart();
if ( result_buffer == mEnd.mBuffer )
aFragment.mEnd = mEnd.mPosInBuffer;
else
aFragment.mEnd = result_buffer->DataEnd();
aFragment.mFragmentIdentifier = result_buffer;
return aFragment.mStart + aOffset;
}
return 0;
}
/**
* |nsSlidingString|
*/
nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
: nsSlidingSubstring(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd)))
{
// nothing else to do here
}
void
nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd )
{
Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd);
Buffer* old_last_buffer = mBufferList->GetLastBuffer();
mBufferList->LinkBuffer(old_last_buffer, new_buffer, 0);
mLength += new_buffer->DataLength();
mEnd.PointAfter(new_buffer);
}
void
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
* that if called for a point after the end of all extant token strings, that no token string
* or the work string will be invalidated.
*
* This routine is protected because it is the responsibility of the derived class to keep those promises.
*/
{
Position insertPos(aInsertPoint);
mBufferList->SplitBuffer(insertPos, nsSharedBufferList::kSplitCopyRightData);
// splitting to the right keeps the work string and any extant token pointing to and
// holding a reference count on the same buffer
Buffer* new_buffer = nsSharedBufferList::NewSingleAllocationBuffer(aReadable, 0);
// make a new buffer with all the data to insert...
// BULLSHIT ALERT: we may have empty space to re-use in the split buffer, measure the cost
// of this and decide if we should do the work to fill it
Buffer* buffer_to_split = insertPos.mBuffer;
mBufferList->LinkBuffer(buffer_to_split, new_buffer, buffer_to_split->mNext);
mLength += aReadable.Length();
mEnd.PointAfter(mBufferList->GetLastBuffer());
}
void
nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter )
{
Position old_start(mStart);
mStart = aIter;
mLength -= Position::Distance(old_start, mStart);
mStart.mBuffer->AcquireNonOwningReference();
old_start.mBuffer->ReleaseNonOwningReference();
mBufferList->DiscardUnreferencedPrefix(old_start.mBuffer);
}
const PRUnichar*
nsSlidingString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
{
return nsSlidingSubstring::GetReadableFragment(aFragment, aRequest, aOffset);
}

View File

@@ -1,182 +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 "nsXPIDLString.h"
#if DEBUG_STRING_STATS
size_t nsXPIDLString::sCreatedCount = 0;
size_t nsXPIDLString::sAliveCount = 0;
size_t nsXPIDLString::sHighWaterCount = 0;
size_t nsXPIDLString::sAssignCount = 0;
size_t nsXPIDLString::sShareCount = 0;
size_t nsXPIDLCString::sCreatedCount = 0;
size_t nsXPIDLCString::sAliveCount = 0;
size_t nsXPIDLCString::sHighWaterCount = 0;
size_t nsXPIDLCString::sAssignCount = 0;
size_t nsXPIDLCString::sShareCount = 0;
#endif
template <class CharT>
class nsImportedStringHandle
: public nsFlexBufferHandle<CharT>
{
public:
nsImportedStringHandle() : nsFlexBufferHandle<CharT>(0, 0, 0, 0) { }
CharT** AddressOfDataStart() { return &(this->mDataStart); }
void RecalculateBoundaries() const;
};
template <class CharT>
void
nsImportedStringHandle<CharT>::RecalculateBoundaries() const
{
size_t data_length = 0;
size_t storage_length = 0;
CharT* data_start = NS_CONST_CAST(CharT*, this->DataStart());
if ( data_start )
{
data_length = nsCharTraits<CharT>::length(data_start);
storage_length = data_length + 1;
}
nsImportedStringHandle<CharT>* mutable_this = NS_CONST_CAST(nsImportedStringHandle<CharT>*, this);
mutable_this->DataEnd(data_start+data_length);
mutable_this->StorageStart(data_start);
mutable_this->StorageEnd(data_start+storage_length);
}
#if DEBUG_STRING_STATS
const nsBufferHandle<PRUnichar>*
nsXPIDLString::GetFlatBufferHandle() const
{
--sShareCount;
return GetSharedBufferHandle();
}
const nsBufferHandle<PRUnichar>*
nsXPIDLString::GetBufferHandle() const
{
--sShareCount;
return GetSharedBufferHandle();
}
void
nsXPIDLString::DebugPrintStats( FILE* aOutFile )
{
fprintf(aOutFile, "nsXPIDLString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n",
sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount);
}
#endif
const nsSharedBufferHandle<PRUnichar>*
nsXPIDLString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<PRUnichar>* answer = NS_STATIC_CAST(const nsImportedStringHandle<PRUnichar>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
++sShareCount;
#endif
return answer;
}
PRUnichar**
nsXPIDLString::PrepareForUseAsOutParam()
{
nsImportedStringHandle<PRUnichar>* handle = new nsImportedStringHandle<PRUnichar>();
NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|.");
mBuffer = handle;
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
}
#if DEBUG_STRING_STATS
const nsBufferHandle<char>*
nsXPIDLCString::GetFlatBufferHandle() const
{
--sShareCount;
return GetSharedBufferHandle();
}
const nsBufferHandle<char>*
nsXPIDLCString::GetBufferHandle() const
{
--sShareCount;
return GetSharedBufferHandle();
}
void
nsXPIDLCString::DebugPrintStats( FILE* aOutFile )
{
fprintf(aOutFile, "nsXPIDLCString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n",
sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount);
}
#endif
const nsSharedBufferHandle<char>*
nsXPIDLCString::GetSharedBufferHandle() const
{
const nsImportedStringHandle<char>* answer = NS_STATIC_CAST(const nsImportedStringHandle<char>*, mBuffer.get());
if ( answer && !answer->DataEnd() )
answer->RecalculateBoundaries();
#if DEBUG_STRING_STATS
++sShareCount;
#endif
return answer;
}
char**
nsXPIDLCString::PrepareForUseAsOutParam()
{
nsImportedStringHandle<char>* handle = new nsImportedStringHandle<char>();
NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|.");
mBuffer = handle;
#if DEBUG_STRING_STATS
++sAssignCount;
#endif
return handle->AddressOfDataStart();
}

View File

@@ -1,37 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src obsolete
#ifdef ENABLE_TESTS
#DIRS += \
# tests
#endif
include $(topsrcdir)/config/rules.mk

View File

@@ -1,29 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

View File

@@ -1,29 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1>
<p>
<span class="LXRLONGDESC"></span>
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
/*
* 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)
*/
/*
* Mac build settings for the release string library
*/
#include "MacPrefix.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

View File

@@ -1,30 +0,0 @@
/*
* 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)
*/
/*
* Mac build settings for the debug string library
*/
#include "MacPrefix_debug.h"
// while we're still a part of xpcom, make stuff get exported
#define _IMPL_NS_COM 1

View File

@@ -1,34 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..
DIRS= public \
src \
obsolete \
#!if !defined(DISABLE_TESTS)
# tests \
#!endif
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,26 +0,0 @@
#
# 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)
#
nsStr.h
nsString.h
nsString2.h

View File

@@ -1,58 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
LIBRARY_NAME = string_obsolete_s
REQUIRES = unicharutil xpcom
CPPSRCS = \
nsStr.cpp \
nsString.cpp \
nsString2.cpp \
$(NULL)
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
# we don't want the shared lib, but we want to force the creation of a
# static lib.
FORCE_STATIC_LIB = 1
# Force use of PIC
FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
DEFINES += -D_IMPL_NS_COM -D_IMPL_NS_BASE

View File

@@ -1,35 +0,0 @@
<html>
<!--
- 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)
-->
<body>
<h1><span class="LXRSHORTDESC">original string implementations soon to be replaced (the names you are using will still be good)</span></h1>
<p>
<span class="LXRLONGDESC">These are the original string implementations by rickg and others.
Most of the code here will be made obsolete by the new shared-buffer string (see bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=53065">#53065</a>).
For the most part, this change is intended to be transparent to clients.
The type names you are using for strings now, e.g., nsString, nsAutoString, nsXPIDLString, will still be good,
they will just refer to better, but compatible, implementations.
If you're interested in learning how strings work, you probably want to start with
<a href="http://lxr.mozilla.org/seamonkey/source/string/public/nsAReadableString.h">nsAReadableString</a>.</span>
</p>
</body>
</html>

View File

@@ -1,994 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
/* bufferRoutines.h --- rickg's original string manipulation underpinnings;
this code will be made obsolete by the new shared-buffer string (see bug #53065)
*/
#ifndef _BUFFERROUTINES_H
#define _BUFFERROUTINES_H
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/******************************************************************************************
MODULE NOTES:
This file contains the workhorse copy and shift functions used in nsStrStruct.
Ultimately, I plan to make the function pointers in this system available for
use by external modules. They'll be able to install their own "handlers".
Not so, today though.
*******************************************************************************************/
#include "nsCRT.h"
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
#include "nsUnicharUtilCIID.h"
#include "nsIServiceManager.h"
#include "nsICaseConversion.h"
#endif
#endif /* XPCOM_STANDALONE */
#define KSHIFTLEFT (0)
#define KSHIFTRIGHT (1)
// uncomment the following line to caught nsString char* casting problem
//#define DEBUG_ILLEGAL_CAST_UP
//#define DEBUG_ILLEGAL_CAST_DOWN
#if defined(DEBUG_ILLEGAL_CAST_UP) || defined(DEBUG_ILLEGAL_CAST_DOWN)
static PRBool track_illegal = PR_TRUE;
static PRBool track_latin1 = PR_TRUE;
#ifdef XP_UNIX
#include "nsTraceRefcnt.h"
class CTraceFile {
public:
CTraceFile() {
mFile = fopen("nsStringTrace.txt" , "a+");
}
~CTraceFile() {
fflush(mFile);
fclose(mFile);
}
void ReportCastUp(const char* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT= %s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const char* s=data;
while(*s) {
if(*s & 0x80) {
fprintf(mFile, "[%2X]", (char)*s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
void ReportCastDown(const PRUnichar* data, const char* msg)
{
if(mFile) {
fprintf(mFile, "ERRORTEXT=%s\n", msg);
fprintf(mFile, "BEGINDATA\n");
const PRUnichar* s=data;
while(*s) {
if(*s & 0xFF80) {
fprintf(mFile, "\\u%X", *s);
} else {
fprintf(mFile, "%c", *s);
}
s++;
}
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
}
}
private:
FILE* mFile;
};
static CTraceFile gTrace;
#define TRACE_ILLEGAL_CAST_UP(c, s, m) if(!(c)) gTrace.ReportCastUp(s,m);
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) if(!(c)) gTrace.ReportCastDown(s,m);
#else // XP_UNIX
#define TRACE_ILLEGAL_CAST_UP(c, s, m) NS_ASSERTION((c), (m))
#define TRACE_ILLEGAL_CAST_DOWN(c, s, m) NS_ASSERTION((c), (m))
#endif //XP_UNIX
#endif
inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) {
return ((PRUnichar*)aString)[anIndex];
}
inline PRUnichar GetCharAt(const char* aString,PRUint32 anIndex) {
return (PRUnichar)aString[anIndex];
}
//----------------------------------------------------------------------------------------
//
// This set of methods is used to shift the contents of a char buffer.
// The functions are differentiated by shift direction and the underlying charsize.
//
/**
* This method shifts single byte characters left by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where left-shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anOffset;
char* src = aDest+anOffset+aCount;
memmove(dst,src,aLength-(aCount+anOffset));
}
/**
* This method shifts single byte characters right by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
char* src = aDest+anOffset;
char* dst = aDest+anOffset+aCount;
memmove(dst,src,aLength-anOffset);
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "cut"
*/
void ShiftDoubleCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftDoubleCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* dst = root+anOffset;
PRUnichar* src = root+anOffset+aCount;
memmove(dst,src,(aLength-(aCount+anOffset))*sizeof(PRUnichar));
}
/**
* This method shifts unicode characters by a given amount from an given offset.
* @update gess 01/04/99
* @param aDest is a ptr to a cstring where the shift is to be performed
* @param aLength is the known length of aDest
* @param anOffset is the index into aDest where shifting shall begin
* @param aCount is the number of chars to be "inserted"
*/
void ShiftDoubleCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
void ShiftDoubleCharsRight(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* root=(PRUnichar*)aDest;
PRUnichar* src = root+anOffset;
PRUnichar* dst = root+anOffset+aCount;
memmove(dst,src,sizeof(PRUnichar)*(aLength-anOffset));
}
typedef void (*ShiftChars)(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount);
ShiftChars gShiftChars[2][2]= {
{&ShiftCharsLeft,&ShiftCharsRight},
{&ShiftDoubleCharsLeft,&ShiftDoubleCharsRight}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to copy one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* Going 1 to 1 is easy, since we assume ascii. No conversions are necessary.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars1To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* dst = aDest+anDestOffset;
char* src = (char*)aSource+anOffset;
memcpy(dst,src,aCount);
}
/**
* Going 1 to 2 requires a conversion from ascii to unicode. This can be expensive.
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars1To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars1To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
const unsigned char* first= (const unsigned char*)aSource+anOffset;
const unsigned char* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_UP
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
*to=(PRUnichar)(*first);
#ifdef DEBUG_ILLEGAL_CAST_UP
if(track_illegal && track_latin1 && ((*to)& 0x80))
illegal= PR_TRUE;
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_UP
TRACE_ILLEGAL_CAST_UP((!illegal), aSource, "illegal cast up in CopyChars1To2");
#endif
}
/**
* Going 2 to 1 requires a conversion from unicode down to ascii. This can be lossy.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
char* to = aDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
const PRUnichar* first= theSource+anOffset;
const PRUnichar* last = first+aCount;
#ifdef DEBUG_ILLEGAL_CAST_DOWN
PRBool illegal= PR_FALSE;
#endif
//now loop over characters, shifting them left...
while(first<last) {
if(*first<256)
*to=(char)*first;
else {
*to='.';
NS_ASSERTION( (*first < 256), "data in U+0100-U+FFFF will be lost");
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
if(track_illegal) {
if(track_latin1) {
if(*first & 0xFF80)
illegal = PR_TRUE;
} else {
if(*first & 0xFF00)
illegal = PR_TRUE;
} // track_latin1
} // track_illegal
#endif
to++;
first++;
}
#ifdef DEBUG_ILLEGAL_CAST_DOWN
TRACE_ILLEGAL_CAST_DOWN((!illegal), theSource, "illegal cast down in CopyChars2To1");
#endif
}
/**
* Going 2 to 2 is fast and efficient.
* @update gess 01/04/99
* @param aDest is the destination buffer
* @param aDestOffset is the pos to start copy to in the dest buffer
* @param aSource is the source buffer
* @param anOffset is the offset to start copying from in the source buffer
* @param aCount is the (max) number of chars to copy
*/
void CopyChars2To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
void CopyChars2To2(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount) {
PRUnichar* theDest=(PRUnichar*)aDest;
PRUnichar* to = theDest+anDestOffset;
PRUnichar* theSource=(PRUnichar*)aSource;
PRUnichar* from= theSource+anOffset;
memcpy((void*)to,(void*)from,aCount*sizeof(PRUnichar));
}
//--------------------------------------------------------------------------------------
typedef void (*CopyChars)(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32 anOffset,PRUint32 aCount);
CopyChars gCopyChars[2][2]={
{&CopyChars1To1,&CopyChars1To2},
{&CopyChars2To1,&CopyChars2To2}
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to search a buffer looking for a char.
//
/**
* This methods cans the given buffer for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* left= aDest+anOffset;
const char* last= left+aCount;
const char* max = aDest+aDestLength;
const char* end = (last<max) ? last : max;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-aDest;
++left;
}
}
else {
PRInt32 theMax = end-left;
if(0<theMax) {
unsigned char theChar = (unsigned char) aChar;
const char* result=(const char*)memchr(left, (int)theChar, theMax);
if(result) {
return result-aDest;
}
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 FindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=0;
if(aCount<0)
aCount = (PRInt32)aDestLength;
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* left = root+anOffset;
const PRUnichar* last = left+aCount;
const PRUnichar* max = root+aDestLength;
const PRUnichar* end = (last<max) ? last : max;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(left<end){
if(nsCRT::ToUpper(*left)==theChar)
return left-root;
++left;
}
}
else {
while(left<end){
if(*left==aChar)
return (left-root);
++left;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer (in reverse) for the given char
*
* @update gess 02/17/00
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = PRInt32(aDestLength);
if((aChar<256) && (0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
//We'll only search if the given aChar is within the normal ascii a range,
//(Since this string is definitely within the ascii range).
if(0<aCount) {
const char* rightmost = aDest+anOffset;
const char* min = rightmost-aCount+1;
const char* leftmost = (min<aDest) ? aDest: min;
if(aIgnoreCase) {
char theChar=(char)nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
else {
char theChar=(char)aChar;
while(leftmost<=rightmost){
if((*rightmost)==theChar)
return rightmost-aDest;
--rightmost;
}
}
}
}
return kNotFound;
}
/**
* This methods cans the given buffer for the given char
*
* @update gess 3/25/98
* @param aDest is the buffer to be searched
* @param aDestLength is the size (in char-units, not bytes) of the buffer
* @param anOffset is the start pos to begin searching
* @param aChar is the target character we're looking for
* @param aIgnorecase tells us whether to use a case sensitive search
* @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
* @return index of pos if found, else -1 (kNotFound)
*/
inline PRInt32 RFindChar2(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDestLength-1;
if(aCount<0)
aCount = PRInt32(aDestLength);
if((0<aDestLength) && ((PRUint32)anOffset<aDestLength)) {
if(0<aCount) {
const PRUnichar* root = (PRUnichar*)aDest;
const PRUnichar* rightmost = root+anOffset;
const PRUnichar* min = rightmost-aCount+1;
const PRUnichar* leftmost = (min<root) ? root: min;
if(aIgnoreCase) {
PRUnichar theChar=nsCRT::ToUpper(aChar);
while(leftmost<rightmost){
if(nsCRT::ToUpper(*rightmost)==theChar)
return rightmost-root;
--rightmost;
}
}
else {
while(leftmost<=rightmost){
if((*rightmost)==aChar)
return rightmost-root;
--rightmost;
}
}
}
}
return kNotFound;
}
typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase,PRInt32 aCount);
FindChars gFindChars[]={&FindChar1,&FindChar2};
FindChars gRFindChars[]={&RFindChar1,&RFindChar2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to compare one buffer onto another.
// The functions are differentiated by the size of source and dest character sizes.
// WARNING: Your destination buffer MUST be big enough to hold all the source bytes.
// We don't validate these ranges here (this should be done in higher level routines).
//
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp(aStr1,aStr2,aCount);
else result=memcmp(aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result=0;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr1,aStr2,aCount);
else result=nsCRT::strncmp((PRUnichar*)aStr1,aStr2,aCount);
return result;
}
/**
* This method compares the data in one buffer with another
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
else result=nsCRT::strncmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
return result;
}
typedef PRInt32 (*CompareChars)(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase);
CompareChars gCompare[2][2]={
{&Compare1To1,&Compare1To2},
{&Compare2To1,&Compare2To2},
};
//----------------------------------------------------------------------------------------
//
// This set of methods is used to convert the case of strings...
//
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper);
PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper){
PRInt32 result=0;
typedef char chartype;
chartype* cp = (chartype*)aString;
chartype* end = cp + aCount-1;
while (cp <= end) {
chartype ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = chartype('A' + (ch - 'a'));
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = chartype('a' + (ch - 'A'));
}
}
cp++;
}
return result;
}
//----------------------------------------------------------------------------------------
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
class HandleCaseConversionShutdown3 : public nsIShutdownListener {
public :
NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service);
HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); }
virtual ~HandleCaseConversionShutdown3(void) {}
NS_DECL_ISUPPORTS
};
static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
static nsICaseConversion * gCaseConv = 0;
NS_IMPL_ISUPPORTS1(HandleCaseConversionShutdown3, nsIShutdownListener);
nsresult HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) {
if (cid.Equals(kUnicharUtilCID)) {
NS_ASSERTION(service == gCaseConv, "wrong service!");
if(gCaseConv){
gCaseConv->Release();
gCaseConv = 0;
}
}
return NS_OK;
}
class CCaseConversionServiceInitializer {
public:
CCaseConversionServiceInitializer(){
HandleCaseConversionShutdown3* listener =
new HandleCaseConversionShutdown3();
if(listener){
nsServiceManager::GetService(kUnicharUtilCID, NS_GET_IID(nsICaseConversion),(nsISupports**) &gCaseConv, listener);
}
}
};
#endif
#endif /* XPCOM_STANDALONE */
//----------------------------------------------------------------------------------------
/**
* This method performs a case conversion the data in the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be case shifted
* @param aCount is the number of chars to compare
* @param aToUpper tells us whether to convert to upper or lower
* @return 0
*/
PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper);
PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper){
PRUnichar* cp = (PRUnichar*)aString;
PRUnichar* end = cp + aCount-1;
PRInt32 result=0;
#ifndef XPCOM_STANDALONE
#if !defined(RICKG_TESTBED) && !defined(STANDALONE_STRING_TESTS)
static CCaseConversionServiceInitializer gCaseConversionServiceInitializer;
// I18N code begin
if(gCaseConv) {
nsresult err=(aToUpper) ? gCaseConv->ToUpper(cp, cp, aCount) : gCaseConv->ToLower(cp, cp, aCount);
if(NS_SUCCEEDED(err))
return 0;
}
// I18N code end
#endif
#endif /* XPCOM_STANDALONE */
while (cp <= end) {
PRUnichar ch = *cp;
if(aToUpper) {
if ((ch >= 'a') && (ch <= 'z')) {
*cp = PRUnichar('A' + (ch - 'a'));
}
}
else {
if ((ch >= 'A') && (ch <= 'Z')) {
*cp = PRUnichar('a' + (ch - 'A'));
}
}
cp++;
}
return result;
}
typedef PRInt32 (*CaseConverters)(char*,PRUint32,PRBool);
CaseConverters gCaseConverters[]={&ConvertCase1,&ConvertCase2};
//----------------------------------------------------------------------------------------
//
// This set of methods is used compress char sequences in a buffer...
//
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
char* from = aString;
char* end = aString + aLength;
char* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
char theChar = *from++;
*to++=theChar; //always copy this char...
if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - aString;
}
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update rickg 03.23.2000
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* from = (PRUnichar*)aString;
PRUnichar* end = from + aLength;
PRUnichar* to = from;
//this code converts /n, /t, /r into normal space ' ';
//it also compresses runs of whitespace down to a single char...
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (from < end) {
PRUnichar theChar = *from++;
*to++=theChar; //always copy this char...
if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
while (from < end) {
theChar = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
break;
}
} //while
} //if
} //if
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*CompressChars)(char* aString,PRUint32 aCount,const char* aSet);
CompressChars gCompressChars[]={&CompressChars1,&CompressChars2};
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars1(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 StripChars1(char* aString,PRUint32 aLength,const char* aSet){
char* to = aString;
char* from = aString-1;
char* end = aString + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
char theChar = *from;
if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen)){
*to++ = theChar;
}
}
*to = 0;
}
return to - (char*)aString;
}
/**
* This method strips chars in a given set from the given buffer
*
* @update gess 01/04/99
* @param aString is the buffer to be manipulated
* @param aLength is the length of the buffer
* @param aSet tells us which chars to compress from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
* @return the new length of the given buffer
*/
PRInt32 StripChars2(char* aString,PRUint32 aLength,const char* aSet);
PRInt32 StripChars2(char* aString,PRUint32 aLength,const char* aSet){
PRUnichar* to = (PRUnichar*)aString;
PRUnichar* from = (PRUnichar*)aString-1;
PRUnichar* end = to + aLength;
if(aSet && aString && (0 < aLength)){
PRUint32 aSetLen=strlen(aSet);
while (++from < end) {
PRUnichar theChar = *from;
//Note the test for ascii range below. If you have a real unicode char,
//and you're searching for chars in the (given) ascii string, there's no
//point in doing the real search since it's out of the ascii range.
if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,PR_FALSE,aSetLen))){
*to++ = theChar;
}
}
*to = 0;
}
return to - (PRUnichar*)aString;
}
typedef PRInt32 (*StripChars)(char* aString,PRUint32 aCount,const char* aSet);
StripChars gStripChars[]={&StripChars1,&StripChars2};
#endif

View File

@@ -1,49 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
#
DEPTH=..\..
EXPORTS = \
nsStr.h \
nsString.h \
nsString2.h \
$(NULL)
LIBRARY_NAME=string_obsolete_s
LIBRARY=.\$(OBJDIR)\$(LIBRARY_NAME).lib
LCFLAGS = -D_IMPL_NS_COM -D_IMPL_NS_BASE -DWIN32_LEAN_AND_MEAN
CPP_OBJS = \
.\$(OBJDIR)\nsStr.obj \
.\$(OBJDIR)\nsString.obj \
.\$(OBJDIR)\nsString2.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,921 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
#include "nsStr.h"
#include "bufferRoutines.h"
#include <stdio.h> //only used for printf
#include "nsCRT.h"
#include "nsDeque.h"
/******************************************************************************************
MODULE NOTES:
This file contains the nsStr data structure.
This general purpose buffer management class is used as the basis for our strings.
It's benefits include:
1. An efficient set of library style functions for manipulating nsStrs
2. Support for 1 and 2 byte character strings (which can easily be increased to n)
3. Unicode awareness and interoperability.
*******************************************************************************************/
//static const char* kCallFindChar = "For better performance, call FindChar() for targets whose length==1.";
//static const char* kCallRFindChar = "For better performance, call RFindChar() for targets whose length==1.";
static const PRUnichar gCommonEmptyBuffer[1] = {0};
static PRBool gStringAcquiredMemory = PR_TRUE;
/**
* This method initializes all the members of the nsStr structure
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=(char*)gCommonEmptyBuffer;
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
}
/**
* This method initializes all the members of the nsStr structure
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
}
/**
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Destroy(nsStr& aDest) {
if((aDest.mStr) && (aDest.mStr!=(char*)gCommonEmptyBuffer)) {
Free(aDest);
}
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents are not preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aString.mCapacity) {
result=Realloc(aString,aNewLength);
if(aString.mStr)
AddNullTerminator(aString);
}
return result;
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents ARE preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
// the new strategy is, allocate exact size, double on grows
if ( aDest.mCapacity ) {
PRUint32 newCapacity = aDest.mCapacity;
while ( newCapacity < aNewLength )
newCapacity <<= 1;
aNewLength = newCapacity;
}
#endif
result=EnsureCapacity(theTempStr,aNewLength);
if(result) {
if(aDest.mLength) {
StrAppend(theTempStr,aDest,0,aDest.mLength);
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
return result;
}
/**
* Replaces the contents of aDest with aSource, up to aCount of chars.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed.
* @param aSource is where chars are copied from
* @param aCount is the number of chars copied from aSource
*/
void nsStr::StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(&aDest!=&aSource){
StrTruncate(aDest,0);
StrAppend(aDest,aSource,anOffset,aCount);
}
}
/**
* This method appends the given nsStr to this one. Note that we have to
* pay attention to the underlying char-size of both structs.
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aSource is where char are copied from
* @aCount is the number of bytes to be copied
*/
void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount){
if(anOffset<aSource.mLength){
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
if(0<theLength){
PRBool isBigEnough=PR_TRUE;
if(aDest.mLength+theLength > aDest.mCapacity) {
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
}
if(isBigEnough) {
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
}
}
/**
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed
* @param aDestOffset is where in aDest the insertion is to occur
* @param aSource is where chars are copied from
* @param aSrcOffset is where in aSource chars are copied from
* @param aCount is the number of chars from aSource to be inserted into aDest
*/
void nsStr::StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
if(0<aSource.mLength){
if(aDest.mLength){
if(aDestOffset<aDest.mLength){
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
if(aSrcOffset<aSource.mLength) {
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,aDest.mCharSize);
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
if(isBigEnough) {
if(aDestOffset) {
StrAppend(theTempStr,aDest,0,aDestOffset); //first copy leftmost data...
}
StrAppend(theTempStr,aSource,0,aSource.mLength); //next copy inserted (new) data
PRUint32 theRemains=aDest.mLength-aDestOffset;
if(theRemains) {
StrAppend(theTempStr,aDest,aDestOffset,theRemains); //next copy rightmost data
}
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
}
else {
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
}
//finally, make sure to update the string length...
aDest.mLength+=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}//if
//else nothing to do!
}
else StrAppend(aDest,aSource,0,aCount);
}
else StrAppend(aDest,aSource,0,aCount);
}
}
/**
* This method deletes up to aCount chars from aDest
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aDestOffset is where in aDest deletion is to occur
* @param aCount is the number of chars to be deleted in aDest
*/
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
if(aDestOffset<aDest.mLength){
PRUint32 theDelta=aDest.mLength-aDestOffset;
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
if(aDestOffset+theLength<aDest.mLength) {
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
else StrTruncate(aDest,aDestOffset);
}//if
}
/**
* This method truncates the given nsStr at given offset
* @update gess10/30/98
* @param aDest is the nsStr to be truncated
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::StrTruncate(nsStr& aDest,PRUint32 aDestOffset){
if(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
}
}
/**
* This method forces the given string to upper or lowercase
* @update gess1/7/99
* @param aDest is the string you're going to change
* @param aToUpper: if TRUE, then we go uppercase, otherwise we go lowercase
* @return
*/
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
// somehow UnicharUtil return failed, fallback to the old ascii only code
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
}
/**
* This method removes characters from the given set from this string.
* NOTE: aSet is a char*, and it's length is computed using strlen, which assumes null termination.
*
* @update gess 11/7/99
* @param aDest
* @param aSet
* @param aEliminateLeading
* @param aEliminateTrailing
* @return nothing
*/
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
if((aDest.mLength>0) && aSet){
PRInt32 theIndex=-1;
PRInt32 theMax=aDest.mLength;
PRInt32 theSetLen=nsCRT::strlen(aSet);
if(aEliminateLeading) {
while(++theIndex<=theMax) {
PRUnichar theChar=GetCharAt(aDest,theIndex);
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound==thePos)
break;
}
if(0<theIndex) {
if(theIndex<theMax) {
Delete(aDest,0,theIndex);
}
else StrTruncate(aDest,0);
}
}
if(aEliminateTrailing) {
theIndex=aDest.mLength;
PRInt32 theNewLen=theIndex;
while(--theIndex>=0) {
PRUnichar theChar=GetCharAt(aDest,theIndex); //read at end now...
PRInt32 thePos=gFindChars[eOneByte](aSet,theSetLen,0,theChar,PR_FALSE,theSetLen);
if(kNotFound<thePos)
theNewLen=theIndex;
else break;
}
if(theNewLen<theMax) {
StrTruncate(aDest,theNewLen);
}
}
}
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=gCompressChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::StripChars(nsStr& aDest,const char* aSet){
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet);
aDest.mLength=aNewLen;
NSSTR_SEEN(aDest);
}
}
/**************************************************************
Searching methods...
**************************************************************/
/**
* This searches aDest for a given substring
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tells us how many iterations to make from offset; -1 means the full length of the string
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
if(0<=theMaxPos) {
if(anOffset<0)
anOffset=0;
if((0<aDest.mLength) && (anOffset<=theMaxPos) && (aTarget.mLength)) {
if(aCount<0)
aCount = MaxInt(theMaxPos,1);
if(0<aCount) {
PRInt32 aDelta= (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* left = root+(anOffset*aDelta);
const char* last = left+((aCount)*aDelta);
const char* max = root+(theMaxPos*aDelta);
const char* right = (last<max) ? last : max;
while(left<=right){
PRInt32 cmp=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(left,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==cmp) {
return (left-root)/aDelta;
}
left+=aDelta;
} //while
} //if
}
} //if
return kNotFound;
}
/**
* This searches aDest for a given character
*
* @update gess 2/04/00: added aCount argument to restrict search
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @param aCount tell us how many chars to search from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallFindChar);
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
//Note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if((0<aDest.mLength) && (0<aSet.mLength)){
while(++index<(PRInt32)aDest.mLength) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**************************************************************
Reverse Searching methods...
**************************************************************/
/**
* This searches aDest (in reverse) for a given substring
*
* @update gess 2/18/00
* @param aDest string to search
* @param aTarget is the substring you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search (counting from left)
* @param aCount tell us how many iterations to perform from offset
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
if(aCount<0)
aCount = aDest.mLength;
if((0<aDest.mLength) && ((PRUint32)anOffset<aDest.mLength) && (aTarget.mLength)) {
if(0<aCount) {
PRInt32 aDelta = (aDest.mCharSize == eOneByte) ? 1 : 2;
const char* root = aDest.mStr;
const char* destLast = root+(aDest.mLength*aDelta); //pts to last char in aDest (likely null)
const char* rightmost = root+(anOffset*aDelta);
const char* min = rightmost-((aCount-1)*aDelta);
const char* leftmost = (min<root) ? root: min;
while(leftmost<=rightmost) {
//don't forget to divide by delta in next text (bug found by rhp)...
if(aTarget.mLength<=PRUint32((destLast-rightmost)/aDelta)) {
PRInt32 result=(*gCompare[aDest.mCharSize][aTarget.mCharSize])(rightmost,aTarget.mStr,aTarget.mLength,aIgnoreCase);
if(0==result) {
return (rightmost-root)/aDelta;
}
} //if
rightmost-=aDelta;
} //while
}
}
return kNotFound;
}
/**
* This searches aDest (in reverse) for a given character
*
* @update gess 2/04/00
* @param aDest string to search
* @param char is the character you're trying to find.
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search; -1 means start at very end (mLength)
* @param aCount tell us how many iterations to perform from offset; -1 means use full length.
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
return gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
/**
* This searches aDest (in reverese) for a character found in aSet.
*
* @update gess 3/25/98
* @param aDest string to search
* @param aSet contains a list of chars to be searched for
* @param aIgnorecase indicates case sensitivity of search
* @param anOffset tells us where to start the search
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
//NS_PRECONDITION(aSet.mLength!=1,kCallRFindChar);
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
//note that the search is inverted here. We're scanning aDest, one char at a time
//but doing the search against the given set. That's why we use 0 as the offset below.
if(0<aDest.mLength) {
while(--index>=0) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase,aSet.mLength);
if(kNotFound!=thePos)
return index;
} //while
}
return kNotFound;
}
/**
* Compare source and dest strings, up to an (optional max) number of chars
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aCount -- if (-1), then we use length of longer string; if (0<aCount) then it gives the max # of chars to compare
* @param aIgnorecase tells us whether to search with case sensitivity
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
PRInt32 result=0;
if(aCount) {
PRInt32 minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
if(0==minlen) {
if ((aDest.mLength == 0) && (aSource.mLength == 0))
return 0;
if (aDest.mLength == 0)
return -1;
return 1;
}
PRInt32 theCount = (aCount<0) ? minlen: MinInt(aCount,minlen);
result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,theCount,aIgnoreCase);
if (0==result) {
if(-1==aCount) {
//Since the caller didn't give us a length to test, and minlen characters matched,
//we have to assume that the longer string is greater.
if (aDest.mLength != aSource.mLength) {
//we think they match, but we've only compared minlen characters.
//if the string lengths are different, then they don't really match.
result = (aDest.mLength<aSource.mLength) ? -1 : 1;
}
} //if
}
}
return result;
}
/**
* Overwrites the contents of dest at offset with contents of aSource
*
* @param aDest is the first str to compare
* @param aSource is the second str to compare
* @param aDestOffset is the offset within aDest where source should be copied
* @return error code
*/
void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
if(aDest.mLength && aSource.mLength) {
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
//if you're here, then both dest and source have valid lengths
//and there's enough room in dest (at offset) to contain source.
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
}
}
}
//----------------------------------------------------------------------------------------
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
static int mAllocCount=0;
mAllocCount++;
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
//we're given the acount value in charunits; now scale up to next multiple.
PRUint32 theNewCapacity=kDefaultStringSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
}
aDest.mCapacity=theNewCapacity++;
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr = (char*)nsMemory::Alloc(theSize);
#else
// the new strategy is, allocate exact size, double on grows
aDest.mCapacity = aCount;
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
#endif
if(aDest.mStr) {
aDest.mOwnsBuffer=1;
gStringAcquiredMemory=PR_TRUE;
}
else gStringAcquiredMemory=PR_FALSE;
return gStringAcquiredMemory;
}
PRBool nsStr::Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
nsMemory::Free(aDest.mStr);
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
return PR_TRUE;
}
return PR_FALSE;
}
PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
nsStr temp;
memcpy(&temp,&aDest,sizeof(aDest));
PRBool result=Alloc(temp,aCount);
if(result) {
Free(aDest);
aDest.mStr=temp.mStr;
aDest.mCapacity=temp.mCapacity;
aDest.mOwnsBuffer=temp.mOwnsBuffer;
}
return result;
}
/**
* Retrieve last memory error
*
* @update gess 10/11/99
* @return memory error (usually returns PR_TRUE)
*/
PRBool nsStr::DidAcquireMemory(void) {
return gStringAcquiredMemory;
}
//----------------------------------------------------------------------------------------
CBufDescriptor::CBufDescriptor(char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_FALSE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const char* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eOneByte;
mStackBased=aStackBased;
mIsConst=PR_TRUE;
mLength=mCapacity=0;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_FALSE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength) {
mBuffer=(char*)aString;
mCharSize=eTwoByte;
mStackBased=aStackBased;
mLength=mCapacity=0;
mIsConst=PR_TRUE;
if(aString && aCapacity>1) {
mCapacity=aCapacity-1;
mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
if(mLength>PRInt32(mCapacity))
mLength=mCapacity;
}
}
//----------------------------------------------------------------------------------------
PRUint32
nsStr::HashCode(const nsStr& aDest)
{
if (aDest.mCharSize == eTwoByte)
return nsCRT::HashCode(aDest.mUStr);
else
return nsCRT::HashCode(aDest.mStr);
}
#ifdef NS_STR_STATS
#include <ctype.h>
#ifdef XP_MAC
#define isascii(c) ((unsigned)(c) < 0x80)
#endif
void
nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
{
PRInt32 printLen = (PRInt32)aDest.mLength;
if (aDest.mCharSize == eOneByte) {
const char* chars = aDest.mStr;
while (printLen-- && (!truncate || *chars != '\n')) {
fputc(*chars++, out);
}
}
else {
const PRUnichar* chars = aDest.mUStr;
while (printLen-- && (!truncate || *chars != '\n')) {
if (isascii(*chars))
fputc((char)(*chars++), out);
else
fputc('-', out);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// String Usage Statistics Routines
static PLHashTable* gStringInfo = nsnull;
PRLock* gStringInfoLock = nsnull;
PRBool gNoStringInfo = PR_FALSE;
nsStringInfo::nsStringInfo(nsStr& str)
: mCount(0)
{
nsStr::Initialize(mStr, str.mCharSize);
nsStr::StrAssign(mStr, str, 0, -1);
// nsStr::Print(mStr, stdout);
// fputc('\n', stdout);
}
PR_EXTERN(PRHashNumber)
nsStr_Hash(const void* key)
{
nsStr* str = (nsStr*)key;
return nsStr::HashCode(*str);
}
PR_EXTERN(PRIntn)
nsStr_Compare(const void *v1, const void *v2)
{
nsStr* str1 = (nsStr*)v1;
nsStr* str2 = (nsStr*)v2;
return nsStr::StrCompare(*str1, *str2, -1, PR_FALSE) == 0;
}
nsStringInfo*
nsStringInfo::GetInfo(nsStr& str)
{
if (gStringInfo == nsnull) {
gStringInfo = PL_NewHashTable(1024,
nsStr_Hash,
nsStr_Compare,
PL_CompareValues,
NULL, NULL);
gStringInfoLock = PR_NewLock();
}
PR_Lock(gStringInfoLock);
nsStringInfo* info =
(nsStringInfo*)PL_HashTableLookup(gStringInfo, &str);
if (info == NULL) {
gNoStringInfo = PR_TRUE;
info = new nsStringInfo(str);
if (info) {
PLHashEntry* e = PL_HashTableAdd(gStringInfo, &info->mStr, info);
if (e == NULL) {
delete info;
info = NULL;
}
}
gNoStringInfo = PR_FALSE;
}
PR_Unlock(gStringInfoLock);
return info;
}
void
nsStringInfo::Seen(nsStr& str)
{
if (!gNoStringInfo) {
nsStringInfo* info = GetInfo(str);
info->mCount++;
}
}
void
nsStringInfo::Report(FILE* out)
{
if (gStringInfo) {
fprintf(out, "\n== String Stats\n");
PL_HashTableEnumerateEntries(gStringInfo, nsStringInfo::ReportEntry, out);
}
}
PRIntn
nsStringInfo::ReportEntry(PLHashEntry *he, PRIntn i, void *arg)
{
nsStringInfo* entry = (nsStringInfo*)he->value;
FILE* out = (FILE*)arg;
fprintf(out, "%d ==> (%d) ", entry->mCount, entry->mStr.mLength);
nsStr::Print(entry->mStr, out, PR_TRUE);
fputc('\n', out);
return HT_ENUMERATE_NEXT;
}
#endif // NS_STR_STATS
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,532 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsStr.h --- the underlying buffer for rickg's original string implementations;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsStr
#define _nsStr
#ifndef nsStringDefines_h___
#include "nsStringDefines.h"
#endif
/***********************************************************************
MODULE NOTES:
1. There are two philosophies to building string classes:
A. Hide the underlying buffer & offer API's allow indirect iteration
B. Reveal underlying buffer, risk corruption, but gain performance
We chose the option B for performance reasons.
2 Our internal buffer always holds capacity+1 bytes.
The nsStr struct is a simple structure (no methods) that contains
the necessary info to be described as a string. This simple struct
is manipulated by the static methods provided in this class.
(Which effectively makes this a library that works on structs).
There are also object-based versions called nsString and nsAutoString
which use nsStr but makes it look at feel like an object.
***********************************************************************/
/***********************************************************************
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated. However,
since it maintains a length byte, you can store NULL's inside
the string. Just be careful passing such buffers to 3rd party
API's that assume that NULL always terminate the buffer.
2. nsCStrings can be upsampled into nsString without data loss
3. Char searching is faster than string searching. Use char interfaces
if your needs will allow it.
4. It's easy to use the stack for nsAutostring buffer storage (fast too!).
See the CBufDescriptor class in this file.
5. If you don't provide the optional count argument to Append() and Insert(),
the method will assume that the given buffer is terminated by the first
NULL it encounters.
6. Downsampling from nsString to nsCString can be lossy -- avoid it if possible!
7. Calls to ToNewCString() and ToNewUnicode() should be matched with calls to nsMemory::Free().
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsMemory
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenuously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
--- FAQ ---
Q. When should I use nsCString instead of nsString?
A. You should really try to stick with nsString, so that we stay as unicode
compliant as possible. But there are cases where an interface you use requires
a char*. In such cases, it's fair to use nsCString.
Q. I know that my string is going to be a certain size. Can I pre-size my nsString?
A. Yup, here's how:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
Q. Should nsAutoString or nsCAutoString ever live on the heap?
A. That would be counterproductive. The point of nsAutoStrings is to preallocate your
buffers, and to auto-destroy the string when it goes out of scope.
Q. I already have a char*. Can I use the nsString functionality on that buffer?
A. Yes you can -- by using an intermediate class called CBufDescriptor.
The CBufDescriptor class is used to tell nsString about an external buffer (heap or stack) to use
instead of it's own internal buffers. Here's an example:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString/nsCString interfaces. Cool, huh?
Note however that just like any other nsStringXXX use, if you write more data
than will fit in the buffer, a visit to the heap manager will be in order.
Q. What is the simplest way to get from a char* to PRUnichar*?
A. The simplest way is by construction (or assignment):
{
char* theBuf = "hello there";
nsAutoString foo(theBuf);
}
If you don't want the char* to be copied into the nsAutoString, the use a
CBufDescriptor instead.
**********************************************************************************/
#include "nscore.h"
#include "nsMemory.h"
#include <string.h>
#include <stdio.h>
#include "plhash.h"
//----------------------------------------------------------------------------------------
enum eCharSize {eOneByte=0,eTwoByte=1};
#define kDefaultCharSize eTwoByte
#define kRadix10 (10)
#define kRadix16 (16)
#define kAutoDetect (100)
#define kRadixUnknown (kAutoDetect+1)
#define IGNORE_CASE (PR_TRUE)
const PRInt32 kDefaultStringSize = 64;
const PRInt32 kNotFound = -1;
//----------------------------------------------------------------------------------------
class NS_COM CBufDescriptor {
public:
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(PRUnichar* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
char* mBuffer;
eCharSize mCharSize;
PRUint32 mCapacity;
PRInt32 mLength;
PRBool mStackBased;
PRBool mIsConst;
};
//----------------------------------------------------------------------------------------
struct NS_COM nsStr {
nsStr() {
MOZ_COUNT_CTOR(nsStr);
}
~nsStr() {
MOZ_COUNT_DTOR(nsStr);
}
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,eCharSize aCharSize);
/**
* This method initializes an nsStr for use
*
* @update gess 01/04/99
* @param aString is the nsStr to be initialized
* @param aCharSize tells us the requested char size (1 or 2 bytes)
*/
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
/**
* This method destroys the given nsStr, and *MAY*
* deallocate it's memory depending on the setting
* of the internal mOwnsBUffer flag.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used to the nsStr
*/
static void Destroy(nsStr& aDest);
/**
* These methods are where memory allocation/reallocation occur.
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used on the nsStr
* @return
*/
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
static PRBool GrowCapacity(nsStr& aString,PRUint32 aNewLength);
/**
* These methods are used to append content to the given nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to assign contents of a source string to dest string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
/**
* These methods are used to insert content from source string to the dest nsStr
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to insert
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrInsert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
/**
* This method deletes chars from the given str.
* The given allocator may choose to resize the str as well.
*
* @update gess 01/04/99
* @param aDest is the nsStr to be deleted from
* @param aDestOffset tells us where in dest to start deleting
* @param aCount tells us the (max) # of chars to delete
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
/**
* This method is used to truncate the given string.
* The given allocator may choose to resize the str as well (but it's not likely).
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrTruncate(nsStr& aDest,PRUint32 aDestOffset);
/**
* This method is used to perform a case conversion on the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be case shifted
* @param toUpper tells us to go upper vs. lower
*/
static void ChangeCase(nsStr& aDest,PRBool aToUpper);
/**
* This method trims chars (given in aSet) from the edges of given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to remove from given buffer
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method compresses duplicate runs of a given char from the given buffer
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void CompressSet(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing);
/**
* This method removes all occurances of chars in given set from aDest
*
* @update gess 01/04/99
* @param aDest is the buffer to be manipulated
* @param aSet tells us which chars to compress from given buffer
* @param aChar is the replacement char
* @param aEliminateLeading tells us whether to strip chars from the start of the buffer
* @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
*/
static void StripChars(nsStr& aDest,const char* aSet);
/**
* This method compares the data bewteen two nsStr's
*
* @update gess 01/04/99
* @param aStr1 is the first buffer to be compared
* @param aStr2 is the 2nd buffer to be compared
* @param aCount is the number of chars to compare
* @param aIgnorecase tells us whether to use a case-sensitive comparison
* @return -1,0,1 depending on <,==,>
*/
static PRInt32 StrCompare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase);
/**
* These methods scan the given string for 1 or more chars in a given direction
*
* @update gess 01/04/99
* @param aDest is the nsStr to be searched to
* @param aSource (or aChar) is the substr we're looking to find
* @param aIgnoreCase tells us whether to search in a case-sensitive manner
* @param anOffset tells us where in the dest string to start searching
* @return the index of the source (substr) in dest, or -1 (kNotFound) if not found.
*/
static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount);
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
static PRBool DidAcquireMemory(void);
/**
* Returns a hash code for the string for use in a PLHashTable.
*/
static PRUint32 HashCode(const nsStr& aDest);
#ifdef NS_STR_STATS
/**
* Prints an nsStr. If truncate is true, the string is only printed up to
* the first newline. (Note: The current implementation doesn't handle
* non-ascii unicode characters.)
*/
static void Print(const nsStr& aDest, FILE* out, PRBool truncate = PR_FALSE);
#endif
PRUint32 mLength;
PRUint32 mCapacity;
eCharSize mCharSize;
PRBool mOwnsBuffer;
union {
char* mStr;
PRUnichar* mUStr;
};
private:
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
static PRBool Free(nsStr& aString);
};
/**************************************************************
A couple of tiny helper methods used in the string classes.
**************************************************************/
inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt1 : anInt2;
}
inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
return (anInt1<anInt2) ? anInt2 : anInt1;
}
inline void AddNullTerminator(nsStr& aDest) {
if(eTwoByte==aDest.mCharSize)
aDest.mUStr[aDest.mLength]=0;
else aDest.mStr[aDest.mLength]=0;
}
/**
* Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
*
* Return the given buffer to the heap manager. Calls allocator::Free()
* @return string length
*/
inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
/**
* This method is used to access a given char in the given string
*
* @update gess 01/04/99
* @param aDest is the nsStr to be appended to
* @param anIndex tells us where in dest to get the char from
* @return the given char, or 0 if anIndex is out of range
*/
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
if(anIndex<aDest.mLength) {
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
}//if
return 0;
}
#ifdef NS_STR_STATS
class nsStringInfo {
public:
nsStringInfo(nsStr& str);
~nsStringInfo() {}
static nsStringInfo* GetInfo(nsStr& str);
static void Seen(nsStr& str);
static void Report(FILE* out = stdout);
static PRIntn ReportEntry(PLHashEntry *he, PRIntn i, void *arg);
protected:
nsStr mStr;
PRUint32 mCount;
};
#define NSSTR_SEEN(str) nsStringInfo::Seen(str)
#else // !NS_STR_STATS
#define NSSTR_SEEN(str) /* nothing */
#endif // !NS_STR_STATS
#endif // _nsStr

File diff suppressed because it is too large Load Diff

View File

@@ -1,551 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString.h --- rickg's original strings of 1-byte chars, |nsCString| and |nsCAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsCString_
#define _nsCString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "nsString2.h"
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsStr.h"
#include "nsIAtom.h"
#include "nsAString.h"
#include "nsXPIDLString.h"
/* this file will one day be _only_ a compatibility header for clients using the names
|ns[C]String| et al ... which we probably want to support forever.
In the mean time, people are used to getting the names |nsAReadable[C]String| and friends
from here as well; so we must continue to include the other compatibility headers
even though we don't use them ourself.
*/
#include "nsAWritableString.h"
// for compatibility
class NS_COM nsCString :
public nsAFlatCString,
public nsStr {
protected:
virtual const nsBufferHandle<char>* GetFlatBufferHandle() const;
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
public:
virtual const char* get() const { return mStr; }
public:
/**
* Default constructor.
*/
nsCString();
/**
* This is our copy constructor
* @param reference to another nsCString
*/
nsCString(const nsCString& aString);
explicit nsCString( const nsACString& );
explicit nsCString(const char*);
nsCString(const char*, PRInt32);
/**
* Destructor
*
*/
virtual ~nsCString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string capacity
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**********************************************************************
Accessor methods...
*********************************************************************/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsCString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsCString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars(const char* aSet);
void StripChar(PRUnichar aChar,PRInt32 anOffset=0);
void StripChar(char aChar,PRInt32 anOffset=0) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar(PRUnichar aOldChar,PRUnichar aNewChar);
void ReplaceChar(const char* aSet,PRUnichar aNewChar);
void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue);
void ReplaceSubstring(const char* aTarget,const char* aNewValue);
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsCString that is a clone
* of this string.
*
*/
nsCString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return this
*/
nsCString& operator=( const nsCString& aString ) { Assign(aString); return *this; }
nsCString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
//nsCString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCString& operator=( char aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(const PRUnichar*,PRInt32=-1);
void AssignWithConversion( const nsString& aString );
void AssignWithConversion( const nsAString& aString );
void AssignWithConversion(PRUnichar);
/*
* Appends n characters from given string to this,
*
* @param aString is the source to be appended to this
* @param aCount -- number of chars to copy; -1 tells us to compute the strlen for you
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
*
* @return number of chars copied
*/
void AppendWithConversion(const nsString&, PRInt32=-1);
void AppendWithConversion(PRUnichar aChar);
void AppendWithConversion( const nsAString& aString );
void AppendWithConversion(const PRUnichar*, PRInt32=-1);
// Why no |AppendWithConversion(const PRUnichar*, PRInt32)|? --- now I know, because implicit construction hid the need for this routine
void AppendInt(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16
void AppendFloat( double aFloat );
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
// Why no |InsertWithConversion(PRUnichar*)|?
#if 0
virtual void do_AppendFromReadable( const nsACString& );
virtual void do_InsertFromReadable( const nsACString&, PRUint32 );
#endif
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRBool
EqualsWithConversion(const nsXPIDLString &aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return EqualsWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(const nsAFlatCString& aString) const
{
return EqualsIgnoreCase(aString.get(), aString.Length());
}
PRBool EqualsIgnoreCase(const nsAFlatCString& aString, PRInt32 aCount) const
{
return EqualsIgnoreCase(aString.get(), aCount);
}
void DebugDump(void) const;
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( PRUnichar );
void AssignWithConversion( char );
void AssignWithConversion( const char*, PRInt32=-1 );
void AppendWithConversion( char );
void InsertWithConversion( char, PRUint32 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsCString, char)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCString, char)
extern NS_COM int fputs(const nsCString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsCString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsCAutoString : public nsCString {
public:
virtual ~nsCAutoString();
nsCAutoString();
explicit nsCAutoString(const nsCString& );
explicit nsCAutoString(const nsACString& aString);
explicit nsCAutoString(const char* aString);
nsCAutoString(const char* aString,PRInt32 aLength);
explicit nsCAutoString(const CBufDescriptor& aBuffer);
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
public:
nsCAutoString& operator=( const nsACString& aReadable ) { Assign(aReadable); return *this; }
// nsCAutoString& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
nsCAutoString& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
nsCAutoString& operator=( char aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsCAutoString, char)
/**
* A helper class that converts a UCS2 string to UTF8
*/
class NS_COM NS_ConvertUCS2toUTF8
: public nsCAutoString
/*
...
*/
{
public:
explicit
NS_ConvertUCS2toUTF8( const PRUnichar* aString )
{
Append( aString, ~PRUint32(0) /* MAXINT */);
}
NS_ConvertUCS2toUTF8( const PRUnichar* aString, PRUint32 aLength )
{
Append( aString, aLength );
}
explicit
NS_ConvertUCS2toUTF8( PRUnichar aChar )
{
Append( &aChar, 1 );
}
explicit NS_ConvertUCS2toUTF8( const nsAString& aString );
protected:
void Append( const PRUnichar* aString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertUCS2toUTF8( char );
operator const char*() const; // use |get()|
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,681 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Rick Gessner <rickg@netscape.com> (original author)
* Scott Collins <scc@mozilla.org>
*/
/* nsString2.h --- rickg's original strings of 2-byte chars, |nsString| and |nsAutoString|;
these classes will be replaced by the new shared-buffer string (see bug #53065)
*/
#ifndef _nsString_
#define _nsString_
/***********************************************************************
MODULE NOTES:
See nsStr.h for a more general description of string classes.
This version of the nsString class offers many improvements over the
original version:
1. Wide and narrow chars
2. Allocators
3. Much smarter autostrings
4. Subsumable strings
***********************************************************************/
#include "prtypes.h"
#include "nscore.h"
#include <stdio.h>
#include "nsString.h"
#include "nsIAtom.h"
#include "nsStr.h"
#include "nsCRT.h"
#ifndef nsAFlatString_h___
#include "nsAFlatString.h"
#endif
#include "nsXPIDLString.h"
#ifdef STANDALONE_MI_STRING_TESTS
class nsAFlatString { public: virtual ~nsAString() { } };
#endif
class nsISizeOfHandler;
#define nsString2 nsString
#define nsAutoString2 nsAutoString
class NS_COM nsString :
public nsAFlatString,
public nsStr {
protected:
virtual const nsBufferHandle<PRUnichar>* GetFlatBufferHandle() const;
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
public:
virtual const PRUnichar* get() const;
public:
/**
* Default constructor.
*/
nsString();
/**
* This is our copy constructor
* @param reference to another nsString
*/
nsString(const nsString& aString);
explicit nsString(const nsAString&);
explicit nsString(const PRUnichar*);
nsString(const PRUnichar*, PRInt32);
/**
* Destructor
*
*/
virtual ~nsString();
/**
* Retrieve the length of this string
* @return string length
*/
virtual PRUint32 Length() const { return mLength; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
/**
* Call this method if you want to force a different string length
* @update gess7/30/98
* @param aLength -- contains new length for mStr
* @return
*/
void SetLength(PRUint32 aLength);
/**
* Sets the new length of the string.
* @param aLength is new string length.
* @return nada
*/
void SetCapacity(PRUint32 aLength);
/**
* Determine whether or not the characters in this
* string are in store as 1 or 2 byte (unicode) strings.
*
* @return TRUE if ordered.
*/
PRBool IsUnicode(void) const {
PRBool result=PRBool(mCharSize==eTwoByte);
return result;
}
/**********************************************************************
Getters/Setters...
*********************************************************************/
/**
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
*/
const char* GetBuffer(void) const;
/**
* Set nth character.
*/
PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex);
/**********************************************************************
Lexomorphic transforms...
*********************************************************************/
/**
* Converts chars in this to lowercase
* @update gess 7/27/98
*/
void ToLowerCase();
/**
* Converts chars in this to lowercase, and
* stores them in aOut
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToLowerCase(nsString& aString) const;
/**
* Converts chars in this to uppercase
* @update gess 7/27/98
*/
void ToUpperCase();
/**
* Converts chars in this to lowercase, and
* stores them in a given output string
* @update gess 7/27/98
* @param aOut is a string to contain result
*/
void ToUpperCase(nsString& aString) const;
/**
* This method is used to remove all occurances of the
* characters found in aSet from this string.
*
* @param aSet -- characters to be cut from this
* @return *this
*/
void StripChars( const char* aSet );
void StripChar( PRUnichar aChar, PRInt32 anOffset=0 );
void StripChar( char aChar, PRInt32 anOffset=0 ) { StripChar((PRUnichar) (unsigned char)aChar,anOffset); }
void StripChar( PRInt32 anInt, PRInt32 anOffset=0 ) { StripChar((PRUnichar)anInt,anOffset); }
/**
* This method strips whitespace throughout the string
*
* @return this
*/
void StripWhitespace();
/**
* swaps occurence of 1 string for another
*
* @return this
*/
void ReplaceChar( PRUnichar anOldChar, PRUnichar aNewChar );
void ReplaceChar( const char* aSet, PRUnichar aNewChar );
void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue );
void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue );
/**
* This method trims characters found in aTrimSet from
* either end of the underlying string.
*
* @param aTrimSet -- contains chars to be trimmed from
* both ends
* @param aEliminateLeading
* @param aEliminateTrailing
* @param aIgnoreQuotes
* @return this
*/
void Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE,PRBool aIgnoreQuotes=PR_FALSE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressSet(const char* aSet, PRUnichar aChar,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**
* This method strips whitespace from string.
* You can control whether whitespace is yanked from
* start and end of string as well.
*
* @param aEliminateLeading controls stripping of leading ws
* @param aEliminateTrailing controls stripping of trailing ws
* @return this
*/
void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE);
/**********************************************************************
string conversion methods...
*********************************************************************/
/**
* This method constructs a new nsString is a clone of this string.
*
*/
nsString* ToNewString() const;
/**
* Creates an ISOLatin1 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new isolatin1 string
*/
char* ToNewCString() const;
/**
* Creates an UTF8 clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new null-terminated UTF8 string
*/
char* ToNewUTF8String() const;
/**
* Creates a unicode clone of this string
* Note that calls to this method should be matched with calls to
* |nsMemory::Free|.
* @return ptr to new unicode string
*/
PRUnichar* ToNewUnicode() const;
/**
* Copies data from internal buffer onto given char* buffer
* NOTE: This only copies as many chars as will fit in given buffer (clips)
* @param aBuf is the buffer where data is stored
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
* @param aErrorCode will contain error if one occurs
* @return float rep of string value
*/
float ToFloat(PRInt32* aErrorCode) const;
/**
* Perform string to int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return int rep of string value, and possible (out) error code
*/
PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=kRadix10) const;
/**********************************************************************
String manipulation methods...
*********************************************************************/
/**
* assign given string to this string
* @param aStr: buffer to be assigned to this
* @param aCount is the length of the given str (or -1) if you want me to determine its length
* NOTE: IFF you pass -1 as aCount, then your buffer must be null terminated.
* @return this
*/
nsString& operator=( const nsString& aString ) { Assign(aString); return *this; }
nsString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
//nsString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
void AssignWithConversion(char);
void AssignWithConversion(const char*);
void AssignWithConversion(const char*, PRInt32);
void AssignWithConversion(const nsAFlatCString& aCString)
{
AssignWithConversion(aCString.get(), aCString.Length());
}
void AssignWithConversion(const nsAFlatCString& aCString, PRInt32 aCount)
{
AssignWithConversion(aCString.get(), aCount);
}
/*
* Appends n characters from given string to this,
* This version computes the length of your given string
*
* @param aString is the source to be appended to this
* @return number of chars copied
*/
void AppendInt(PRInt32, PRInt32=10); //radix=8,10 or 16
void AppendFloat(double);
void AppendWithConversion(const char*, PRInt32=-1);
void AppendWithConversion(char);
void AppendWithConversion(const nsAFlatCString& aCString)
{
AppendWithConversion(aCString.get(), aCString.Length());
}
void AppendWithConversion(const nsAFlatCString& aCString, PRInt32 aCount)
{
AppendWithConversion(aCString.get(), aCount);
}
virtual void do_AppendFromElement( PRUnichar );
//void InsertWithConversion(char);
void InsertWithConversion(const char*, PRUint32, PRInt32=-1);
/**********************************************************************
Searching methods...
*********************************************************************/
/**
* Search for given substring within this string
*
* @param aString is substring to be sought in this
* @param aIgnoreCase selects case sensitivity
* @param anOffset tells us where in this strig to start searching
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 Find(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=0,PRInt32 aCount=-1) const;
/**
* This method searches this string for the first character
* found in the given charset
* @param aString contains set of chars to be found
* @param anOffset tells us where to start searching in this
* @return -1 if not found, else the offset in this
*/
PRInt32 FindCharInSet(const char* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const PRUnichar* aString,PRInt32 anOffset=0) const;
PRInt32 FindCharInSet(const nsStr& aString,PRInt32 anOffset=0) const;
/**
* This methods scans the string backwards, looking for the given string
* @param aString is substring to be sought in this
* @param aIgnoreCase tells us whether or not to do caseless compare
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aCount tells us how many iterations to make starting at the given offset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* Search for given char within this string
*
* @param aString is substring to be sought in this
* @param anOffset tells us where in this strig to start searching (counting from left)
* @param aIgnoreCase selects case sensitivity
* @param aCount tells us how many iterations to make starting at the given offset
* @return find pos in string, or -1 (kNotFound)
*/
//PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1,PRInt32 aCount=-1) const;
/**
* This method searches this string for the last character
* found in the given string
* @param aString contains set of chars to be found
* @param anOffset tells us where in this strig to start searching (counting from left)
* @return -1 if not found, else the offset in this
*/
PRInt32 RFindCharInSet(const char* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const PRUnichar* aString,PRInt32 anOffset=-1) const;
PRInt32 RFindCharInSet(const nsStr& aString,PRInt32 anOffset=-1) const;
/**********************************************************************
Comparison methods...
*********************************************************************/
/**
* Compares a given string type to this string.
* @update gess 7/27/98
* @param S is the string to be compared
* @param aIgnoreCase tells us how to treat case
* @param aCount tells us how many chars to compare
* @return -1,0,1
*/
PRInt32 CompareWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const nsString& aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRInt32 CompareWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRInt32
CompareWithConversion(const nsXPIDLString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return CompareWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsWithConversion(const nsString &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
PRBool EqualsWithConversion(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aCount=-1) const;
/* a hack to make sure things that used to compile continue to compile
even on compilers that don't have proper |explicit| support */
inline PRBool
EqualsWithConversion(const nsXPIDLString &aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1) const
{
return EqualsWithConversion(aString.get(), aIgnoreCase, aCount);
}
PRBool EqualsAtom(/*FIX: const */nsIAtom* anAtom,PRBool aIgnoreCase) const;
PRBool EqualsIgnoreCase(const nsString& aString) const;
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
PRBool EqualsIgnoreCase(/*FIX: const */nsIAtom *aAtom) const;
/**
* Determine if given buffer is plain ascii
*
* @param aBuffer -- if null, then we test *this, otherwise we test given buffer
* @return TRUE if is all ascii chars or if strlen==0
*/
PRBool IsASCII(const PRUnichar* aBuffer=0);
void DebugDump(void) const;
/**
* Determine if given char is a valid space character
*
* @param aChar is character to be tested
* @return TRUE if is valid space char
*/
static PRBool IsSpace(PRUnichar ch);
/**
* Determine if given char in valid alpha range
*
* @param aChar is character to be tested
* @return TRUE if in alpha range
*/
static PRBool IsAlpha(PRUnichar ch);
/**
* Determine if given char is valid digit
*
* @param aChar is character to be tested
* @return TRUE if char is a valid digit
*/
static PRBool IsDigit(PRUnichar ch);
private:
// NOT TO BE IMPLEMENTED
// these signatures help clients not accidentally call the wrong thing helped by C++ automatic integral promotion
void operator=( char );
void AssignWithConversion( PRUnichar );
void AssignWithConversion( const PRUnichar*, PRInt32=-1 );
void AppendWithConversion( PRUnichar );
void AppendWithConversion( const PRUnichar*, PRInt32=-1 );
void InsertWithConversion( const PRUnichar*, PRUint32, PRInt32=-1 );
};
// NS_DEF_STRING_COMPARISON_OPERATORS(nsString, PRUnichar)
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsString, PRUnichar)
extern NS_COM int fputs(const nsString& aString, FILE* out);
//ostream& operator<<(ostream& aStream,const nsString& aString);
//virtual void DebugDump(ostream& aStream) const;
/**************************************************************
Here comes the AutoString class which uses internal memory
(typically found on the stack) for its default buffer.
If the buffer needs to grow, it gets reallocated on the heap.
**************************************************************/
class NS_COM nsAutoString : public nsString {
public:
virtual ~nsAutoString();
nsAutoString();
nsAutoString(const nsAutoString& aString);
explicit nsAutoString(const nsAString& aString);
explicit nsAutoString(const nsString& aString);
explicit nsAutoString(const PRUnichar* aString);
nsAutoString(const PRUnichar* aString,PRInt32 aLength);
explicit nsAutoString(PRUnichar aChar);
explicit nsAutoString(const CBufDescriptor& aBuffer);
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
private:
void operator=( char ); // NOT TO BE IMPLEMENTED
public:
nsAutoString& operator=( const nsAString& aReadable ) { Assign(aReadable); return *this; }
// nsAutoString& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
nsAutoString& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
nsAutoString& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
/**
* Retrieve the size of this string
* @return string length
*/
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
char mBuffer[kDefaultStringSize<<eTwoByte];
};
// NS_DEF_DERIVED_STRING_OPERATOR_PLUS(nsAutoString, PRUnichar)
class NS_COM NS_ConvertASCIItoUCS2
: public nsAutoString
/*
...
*/
{
public:
explicit
NS_ConvertASCIItoUCS2( const nsACString& aCString );
explicit
NS_ConvertASCIItoUCS2( const nsAFlatCString& aCString )
{
Init( aCString.get(), aCString.Length() );
}
explicit
NS_ConvertASCIItoUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertASCIItoUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertASCIItoUCS2( char );
#if 0
operator const nsDependentString() const
{
return nsDependentString(mUStr, mLength);
}
#endif
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
// NOT TO BE IMPLEMENTED
NS_ConvertASCIItoUCS2( PRUnichar );
};
class NS_COM NS_ConvertUTF8toUCS2
: public nsAutoString
{
public:
explicit
NS_ConvertUTF8toUCS2( const nsACString& aCString );
explicit
NS_ConvertUTF8toUCS2( const nsAFlatCString& aCString )
{
Init( aCString.get(), aCString.Length() );
}
explicit
NS_ConvertUTF8toUCS2( const char* aCString )
{
Init( aCString, ~PRUint32(0) /* MAXINT */ );
}
NS_ConvertUTF8toUCS2( const char* aCString, PRUint32 aLength )
{
Init( aCString, aLength );
}
explicit
NS_ConvertUTF8toUCS2( char aChar )
{
Init( &aChar, 1 );
}
protected:
void Init( const char* aCString, PRUint32 aLength );
private:
NS_ConvertUTF8toUCS2( PRUnichar );
};
#endif

View File

@@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDebug.h"
#include "nsMemory.h"
#include "nsXPIDLString.h"
#include "plstr.h"
// If the allocator changes, fix it here.
#define XPIDL_STRING_ALLOC(__len) ((PRUnichar*) nsMemory::Alloc((__len) * sizeof(PRUnichar)))
#define XPIDL_CSTRING_ALLOC(__len) ((char*) nsMemory::Alloc((__len) * sizeof(char)))
#define XPIDL_FREE(__ptr) (nsMemory::Free(__ptr))
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
nsXPIDLString::~nsXPIDLString()
{
if (mBuf)
XPIDL_FREE(mBuf);
}
PRUnichar**
nsXPIDLString::StartAssignmentByValue()
{
if (mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
return &mBuf;
}
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
nsXPIDLCString::~nsXPIDLCString()
{
if (mBuf)
XPIDL_FREE(mBuf);
}
char**
nsXPIDLCString::StartAssignmentByValue()
{
if (mBuf)
XPIDL_FREE(mBuf);
mBuf = 0;
return &mBuf;
}

View File

@@ -1,323 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsXPIDLString.h --- an `|auto_ptr|' for character buffers, this functionality will be replaced
by the new shared-buffer string (see bug #53065)
*/
#ifndef nsXPIDLString_h__
#define nsXPIDLString_h__
/*
A set of string wrapper classes that ease transition to use of XPIDL
interfaces. nsXPIDLString and nsXPIDLCString are to XPIDL `wstring'
and `string' out params as nsCOMPtr is to generic XPCOM interface
pointers. They help you deal with object ownership.
Consider the following interface:
interface nsIFoo {
attribute string Bar;
};
This will generate the following C++ header file:
class nsIFoo {
NS_IMETHOD SetBar(const PRUnichar* aValue);
NS_IMETHOD GetBar(PRUnichar* *aValue);
};
The GetBar() method will allocate a copy of the nsIFoo object's
"bar" attribute, and leave you to deal with freeing it:
nsIFoo* aFoo; // assume we get this somehow
PRUnichar* bar;
aFoo->GetFoo(&bar);
// Use bar here...
printf("bar is %s!\n", bar);
nsMemory::Free(bar);
This makes your life harder, because you need to convolute your code
to ensure that you don't leak `bar'.
Enter nsXPIDLString, which manages the ownership of the allocated
string, and automatically destroys it when the nsXPIDLString goes
out of scope:
nsIFoo* aFoo;
nsXPIDLString bar;
aFoo->GetFoo( getter_Copies(bar) );
// Use bar here...
printf("bar is %s!\n", (const char*) bar);
// no need to remember to nsMemory::Free().
Like nsCOMPtr, nsXPIDLString uses some syntactic sugar to make it
painfully clear exactly what the code expects. You need to wrap an
nsXPIDLString object with `getter_Copies()'
before passing it to a getter: these tell the
nsXPIDLString how ownership is being handled.
In the case of `getter_Copies()', the callee is allocating a copy
(which is usually the case). In the case where the
callee is returning a const reference to `the real deal' (this can
be done using the [shared] attribute in XPIDL) you can just use
a |const char*|.
*/
#include "nscore.h"
#include "nsCom.h"
#include "prtypes.h"
#ifndef __PRUNICHAR__
#define __PRUNICHAR__
typedef PRUint16 PRUnichar;
#endif /* __PRUNICHAR__ */
////////////////////////////////////////////////////////////////////////
// nsXPIDLString
//
// A wrapper for Unicode strings. With the |getter_Copies()|
// helper function, this can be used instead of
// the "naked" |PRUnichar*| interface for |wstring| parameters in
// XPIDL interfaces.
//
class NS_COM nsXPIDLString {
private:
PRUnichar* mBuf;
PRUnichar** StartAssignmentByValue();
public:
/**
* Construct a new, uninitialized wrapper for a Unicode string.
*/
nsXPIDLString() : mBuf(0) {}
~nsXPIDLString();
/**
* Return a reference to the immutable Unicode string.
*/
operator const PRUnichar*() const { return get(); }
/**
* Return a reference to the immutable Unicode string.
*/
const PRUnichar* get() const { return mBuf; }
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLString& mXPIDLString;
public:
GetterCopies(nsXPIDLString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator PRUnichar**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLString& aXPIDLString);
};
friend class GetterCopies;
inline void Adopt( PRUnichar* );
private:
// not to be implemented
nsXPIDLString(nsXPIDLString& /* aXPIDLString */) {}
void operator=(nsXPIDLString& /* aXPIDLString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLString object that is to
* receive an |out| value.
*/
inline nsXPIDLString::GetterCopies
getter_Copies(nsXPIDLString& aXPIDLString)
{
return nsXPIDLString::GetterCopies(aXPIDLString);
}
inline
void
nsXPIDLString::Adopt( PRUnichar* aNewValue )
{
*StartAssignmentByValue() = aNewValue;
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
{
return lhs == rhs.get();
}
inline
PRBool
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
{
return lhs.get() == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLString& rhs)
{
return NS_REINTERPRET_CAST(PRUnichar*, lhs) == NS_STATIC_CAST(const PRUnichar*, rhs);
}
inline
PRBool
operator==(const nsXPIDLString& lhs, int rhs)
{
return NS_STATIC_CAST(const PRUnichar*, lhs) == NS_REINTERPRET_CAST(PRUnichar*, rhs);
}
#endif
////////////////////////////////////////////////////////////////////////
// nsXPIDLCString
//
// A wrapper for Unicode strings. With the |getter_Copies()|
// helper function, this can be used instead of
// the "naked" |char*| interface for |string| parameters in XPIDL
// interfaces.
//
class NS_COM nsXPIDLCString {
private:
char* mBuf;
char** StartAssignmentByValue();
public:
/**
* Construct a new, uninitialized wrapper for a single-byte string.
*/
nsXPIDLCString() : mBuf(0) {}
~nsXPIDLCString();
/**
* Return a reference to the immutable single-byte string.
*/
operator const char*() const { return get(); }
/**
* Return a reference to the immutable single-byte string.
*/
const char* get() const { return mBuf; }
// A helper class for assignment-by-value. This class is an
// implementation detail and should not be considered part of the
// public interface.
class NS_COM GetterCopies {
private:
nsXPIDLCString& mXPIDLString;
public:
GetterCopies(nsXPIDLCString& aXPIDLString)
: mXPIDLString(aXPIDLString) {}
operator char**() {
return mXPIDLString.StartAssignmentByValue();
}
friend GetterCopies getter_Copies(nsXPIDLCString& aXPIDLString);
};
friend class GetterCopies;
inline void Adopt( char* );
private:
// not to be implemented
nsXPIDLCString(nsXPIDLCString& /* aXPIDLString */) {}
void operator=(nsXPIDLCString& /* aXPIDLCString */) {}
};
/**
* Use this function to "wrap" the nsXPIDLCString object that is to
* receive an |out| value.
*/
inline nsXPIDLCString::GetterCopies
getter_Copies(nsXPIDLCString& aXPIDLString)
{
return nsXPIDLCString::GetterCopies(aXPIDLString);
}
inline
void
nsXPIDLCString::Adopt( char* aNewValue )
{
*StartAssignmentByValue() = aNewValue;
}
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
inline
PRBool
operator==(const char* lhs, const nsXPIDLCString& rhs)
{
return lhs == rhs.get();
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, const char* rhs)
{
return lhs.get() == rhs;
}
#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
inline
PRBool
operator==(int lhs, const nsXPIDLCString& rhs)
{
return NS_REINTERPRET_CAST(char*, lhs) == NS_STATIC_CAST(const char*, rhs);
}
inline
PRBool
operator==(const nsXPIDLCString& lhs, int rhs)
{
return NS_STATIC_CAST(const char*, lhs) == NS_REINTERPRET_CAST(char*, rhs);
}
#endif
#endif // nsXPIDLString_h__

View File

@@ -1,52 +0,0 @@
#
# 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)
#
nsAFlatString.h
nsAlgorithm.h
nsAPromiseString.h
nsAReadableString.h
nsAString.h
nsAStringGenerator.h
nsAWritableString.h
nsBufferHandle.h
nsBufferHandleUtils.h
nsCharTraits.h
nsDependentConcatenation.h
nsDependentString.h
nsDependentSubstring.h
nsFragmentedString.h
nsLiteralString.h
nsPrintfCString.h
nsPrivateSharableString.h
nsPromiseFlatString.h
nsReadableUtils.h
nsSharableString.h
nsSharedBufferList.h
nsSlidingString.h
nsStringDefines.h
nsStringFragment.h
nsStringFwd.h
nsStringIterator.h
nsStringIteratorUtils.h
nsStringTraits.h
nsXPIDLString.h

View File

@@ -1,67 +0,0 @@
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = string
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAStringGenerator.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsDependentConcatenation.h \
nsDependentString.h \
nsDependentSubstring.h \
nsFragmentedString.h \
nsLiteralString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseFlatString.h \
nsReadableUtils.h \
nsSharableString.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringDefines.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
nsXPIDLString.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,59 +0,0 @@
#!nmake
#
# 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):
# Johnny Stenback <jst@netscape.com> (original author)
# Scott Collins <scc@mozilla.org>
#
DEPTH=..\..
EXPORTS = \
nsAFlatString.h \
nsAlgorithm.h \
nsAPromiseString.h \
nsAReadableString.h \
nsAString.h \
nsAStringGenerator.h \
nsAWritableString.h \
nsBufferHandle.h \
nsBufferHandleUtils.h \
nsCharTraits.h \
nsDependentConcatenation.h \
nsDependentString.h \
nsDependentSubstring.h \
nsFragmentedString.h \
nsLiteralString.h \
nsPrintfCString.h \
nsPrivateSharableString.h \
nsPromiseFlatString.h \
nsReadableUtils.h \
nsSharableString.h \
nsSharedBufferList.h \
nsSlidingString.h \
nsStringDefines.h \
nsStringFragment.h \
nsStringFwd.h \
nsStringIterator.h \
nsStringIteratorUtils.h \
nsStringTraits.h \
nsXPIDLString.h \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,85 +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)
*/
/* nsAFlatString.h --- */
#ifndef nsAFlatString_h___
#define nsAFlatString_h___
#ifndef nsAString_h___
#include "nsAString.h"
#endif
class NS_COM nsAFlatString
: public nsAString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsString| is really dead
virtual const PRUnichar* get() const;
PRUnichar operator[]( PRUint32 i ) const { return get()[ i ]; }
PRUnichar CharAt( PRUint32 ) const;
virtual PRUint32 Length() const;
// protected: // can't hide these (yet), since I call them from forwarding routines in |nsPromiseFlatString|
public:
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
};
class NS_COM nsAFlatCString
: public nsACString
{
public:
// don't really want this to be virtual, and won't after |obsolete_nsCString| is really dead
virtual const char* get() const;
char operator[]( PRUint32 i ) const { return get()[ i ]; }
char CharAt( PRUint32 ) const;
virtual PRUint32 Length() const;
// protected: // can't hide these (yet), since I call them from forwarding routines in |nsPromiseFlatCString|
public:
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
};
inline
PRUnichar
nsAFlatString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
inline
char
nsAFlatCString::CharAt( PRUint32 i ) const
{
NS_ASSERTION(i<Length(), "|CharAt| out-of-range");
return operator[](i);
}
#endif /* !defined(nsAFlatString_h___) */

Some files were not shown because too many files have changed in this diff Show More