зеркало из https://github.com/mozilla/gecko-dev.git
bug #59429: CVS remove all the files that have moved to the new string library
This commit is contained in:
Родитель
8426cfe13e
Коммит
9524941e34
|
@ -1,967 +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>
|
||||
*/
|
||||
|
||||
/******************************************************************************************
|
||||
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.
|
||||
|
||||
*******************************************************************************************/
|
||||
|
||||
#ifndef _BUFFERROUTINES_H
|
||||
#define _BUFFERROUTINES_H
|
||||
|
||||
#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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
|
||||
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) {
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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 = 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 = 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 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 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 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 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 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 = 'A' + (ch - 'a');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((ch >= 'A') && (ch <= 'Z')) {
|
||||
*cp = '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){
|
||||
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 = 'A' + (ch - 'a');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((ch >= 'A') && (ch <= 'Z')) {
|
||||
*cp = '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){
|
||||
|
||||
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){
|
||||
|
||||
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){
|
||||
|
||||
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){
|
||||
|
||||
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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,866 +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 nsAWritableString_h___
|
||||
#define nsAWritableString_h___
|
||||
|
||||
// See also...
|
||||
#ifndef nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
#endif
|
||||
|
||||
|
||||
template <class CharT>
|
||||
struct nsWritableFragment
|
||||
{
|
||||
CharT* mStart;
|
||||
CharT* mEnd;
|
||||
void* mFragmentIdentifier;
|
||||
|
||||
nsWritableFragment()
|
||||
: mStart(0), mEnd(0), mFragmentIdentifier(0)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT> class basic_nsAWritableString;
|
||||
|
||||
template <class CharT>
|
||||
class nsWritingIterator
|
||||
// : public bidirectional_iterator_tag
|
||||
{
|
||||
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 basic_nsAWritableString<CharT>;
|
||||
|
||||
nsWritableFragment<CharT> mFragment;
|
||||
CharT* mPosition;
|
||||
basic_nsAWritableString<CharT>* mOwningString;
|
||||
|
||||
nsWritingIterator( nsWritableFragment<CharT>& aFragment,
|
||||
CharT* aStartingPosition,
|
||||
basic_nsAWritableString<CharT>& aOwningString )
|
||||
: mFragment(aFragment),
|
||||
mPosition(aStartingPosition),
|
||||
mOwningString(&aOwningString)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Really don't want to call these two operations |+=| and |-=|.
|
||||
* Would prefer a single function, e.g., |advance|, which doesn't imply a constant time operation.
|
||||
*
|
||||
* We'll get rid of these as soon as we can.
|
||||
*/
|
||||
nsWritingIterator<CharT>&
|
||||
operator+=( difference_type n ) // deprecated
|
||||
{
|
||||
return advance(n);
|
||||
}
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
operator-=( difference_type n ) // deprecated
|
||||
{
|
||||
return advance(-n);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <class CharT>
|
||||
nsWritingIterator<CharT>&
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
This file defines the abstract interfaces |nsAWritableString| and
|
||||
|nsAWritableCString|.
|
||||
|
||||
|nsAWritableString| is a string of |PRUnichar|s. |nsAWritableCString| (note the
|
||||
'C') is a string of |char|s.
|
||||
*/
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsAWritableString
|
||||
: public basic_nsAReadableString<CharT>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
// friend class nsWritingIterator<CharT>;
|
||||
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef PRUint32 size_type;
|
||||
typedef PRUint32 index_type;
|
||||
|
||||
typedef nsWritingIterator<CharT> iterator;
|
||||
|
||||
// basic_nsAWritableString(); // auto-generated default constructor OK (we're abstract anyway)
|
||||
// basic_nsAWritableString( const basic_nsAWritableString<CharT>& ); // auto-generated copy-constructor OK (again, only because we're abstract)
|
||||
// ~basic_nsAWritableString(); // auto-generated destructor OK
|
||||
// see below for copy-assignment operator
|
||||
|
||||
virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 = 0 ) = 0;
|
||||
|
||||
/**
|
||||
* Note: measure -- should the |BeginWriting| and |EndWriting| be |inline|?
|
||||
*/
|
||||
nsWritingIterator<CharT>&
|
||||
BeginWriting( nsWritingIterator<CharT>& aResult )
|
||||
{
|
||||
aResult.mOwningString = this;
|
||||
GetWritableFragment(aResult.mFragment, kFirstFragment);
|
||||
aResult.mPosition = aResult.mFragment.mStart;
|
||||
aResult.normalize_forward();
|
||||
return aResult;
|
||||
}
|
||||
|
||||
|
||||
nsWritingIterator<CharT>&
|
||||
EndWriting( nsWritingIterator<CharT>& 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* |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( PRUint32 ) { }
|
||||
|
||||
/**
|
||||
* |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( PRUint32 ) = 0;
|
||||
|
||||
|
||||
void
|
||||
Truncate( PRUint32 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 CharT* aSet );
|
||||
// void StripChar( ... );
|
||||
// void StripWhitespace();
|
||||
// void ReplaceChar( ... );
|
||||
// void ReplaceSubstring( ... );
|
||||
// void Trim( ... );
|
||||
// void CompressSet( ... );
|
||||
// void CompressWhitespace( ... );
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Assign()|, |operator=()|
|
||||
//
|
||||
|
||||
void Assign( const basic_nsAReadableString<CharT>& aReadable ) { AssignFromReadable(aReadable); }
|
||||
void Assign( const nsPromiseReadable<CharT>& aReadable ) { AssignFromPromise(aReadable); }
|
||||
void Assign( const CharT* aPtr ) { aPtr ? do_AssignFromElementPtr(aPtr) : SetLength(0); }
|
||||
void Assign( const CharT* aPtr, PRUint32 aLength ) { do_AssignFromElementPtrLength(aPtr, aLength); }
|
||||
void Assign( CharT aChar ) { do_AssignFromElement(aChar); }
|
||||
|
||||
// copy-assignment operator. I must define my own if I don't want the compiler to make me one
|
||||
basic_nsAWritableString<CharT>& operator=( const basic_nsAWritableString<CharT>& aWritable ) { Assign(aWritable); return *this; }
|
||||
|
||||
basic_nsAWritableString<CharT>& operator=( const basic_nsAReadableString<CharT>& aReadable ) { Assign(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( const nsPromiseReadable<CharT>& aReadable ) { Assign(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( const CharT* aPtr ) { Assign(aPtr); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator=( CharT aChar ) { Assign(aChar); return *this; }
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|, |operator+=()|
|
||||
//
|
||||
|
||||
void Append( const basic_nsAReadableString<CharT>& aReadable ) { AppendFromReadable(aReadable); }
|
||||
void Append( const nsPromiseReadable<CharT>& aReadable ) { AppendFromPromise(aReadable); }
|
||||
void Append( const CharT* aPtr ) { if (aPtr) do_AppendFromElementPtr(aPtr); }
|
||||
void Append( const CharT* aPtr, PRUint32 aLength ) { do_AppendFromElementPtrLength(aPtr, aLength); }
|
||||
void Append( CharT aChar ) { do_AppendFromElement(aChar); }
|
||||
|
||||
basic_nsAWritableString<CharT>& operator+=( const basic_nsAReadableString<CharT>& aReadable ) { Append(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( const nsPromiseReadable<CharT>& aReadable ) { Append(aReadable); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( const CharT* aPtr ) { Append(aPtr); return *this; }
|
||||
basic_nsAWritableString<CharT>& operator+=( CharT 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 basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition ) { InsertFromReadable(aReadable, atPosition); }
|
||||
void Insert( const nsPromiseReadable<CharT>& aReadable, PRUint32 atPosition ) { InsertFromPromise(aReadable, atPosition); }
|
||||
void Insert( const CharT* aPtr, PRUint32 atPosition ) { if (aPtr) do_InsertFromElementPtr(aPtr, atPosition); }
|
||||
void Insert( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength ) { do_InsertFromElementPtrLength(aPtr, atPosition, aLength); }
|
||||
void Insert( CharT aChar, PRUint32 atPosition ) { do_InsertFromElement(aChar, atPosition); }
|
||||
|
||||
|
||||
|
||||
virtual void Cut( PRUint32 cutStart, PRUint32 cutLength );
|
||||
|
||||
|
||||
|
||||
void Replace( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable ) { ReplaceFromReadable(cutStart, cutLength, aReadable); }
|
||||
void Replace( PRUint32 cutStart, PRUint32 cutLength, const nsPromiseReadable<CharT>& aReadable ) { ReplaceFromPromise(cutStart, cutLength, aReadable); }
|
||||
|
||||
private:
|
||||
typedef typename nsCharTraits<CharT>::incompatible_char_type incompatible_char_type;
|
||||
|
||||
// NOT TO BE IMPLEMENTED
|
||||
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, PRUint32 );
|
||||
|
||||
|
||||
protected:
|
||||
void AssignFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
void AssignFromPromise( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AssignFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AssignFromElementPtr( const CharT* );
|
||||
virtual void do_AssignFromElementPtrLength( const CharT*, PRUint32 );
|
||||
virtual void do_AssignFromElement( CharT );
|
||||
|
||||
void AppendFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
void AppendFromPromise( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AppendFromReadable( const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_AppendFromElementPtr( const CharT* );
|
||||
virtual void do_AppendFromElementPtrLength( const CharT*, PRUint32 );
|
||||
virtual void do_AppendFromElement( CharT );
|
||||
|
||||
void InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
void InsertFromPromise( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
virtual void do_InsertFromReadable( const basic_nsAReadableString<CharT>&, PRUint32 );
|
||||
virtual void do_InsertFromElementPtr( const CharT*, PRUint32 );
|
||||
virtual void do_InsertFromElementPtrLength( const CharT*, PRUint32, PRUint32 );
|
||||
virtual void do_InsertFromElement( CharT, PRUint32 );
|
||||
|
||||
void ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
void ReplaceFromPromise( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<CharT>& );
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Assign()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AssignFromReadable( const basic_nsAReadableString<CharT>& rhs )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &rhs )
|
||||
do_AssignFromReadable(rhs);
|
||||
// else, self-assign is a no-op
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AssignFromPromise( const basic_nsAReadableString<CharT>& aReadable )
|
||||
/*
|
||||
...this function is only called when a promise that somehow references |this| is assigned _into_ |this|.
|
||||
E.g.,
|
||||
|
||||
... writable& w ...
|
||||
... readable& r ...
|
||||
|
||||
w = r + w;
|
||||
|
||||
In this example, you can see that unless the characters promised by |w| in |r+w| are resolved before
|
||||
anything starts getting copied into |w|, there will be trouble. They will be overritten by the contents
|
||||
of |r| before being retrieved to be appended.
|
||||
|
||||
We could have a really tricky solution where we tell the promise to resolve _just_ the data promised
|
||||
by |this|, but this should be a rare case, since clients with more local knowledge will know that, e.g.,
|
||||
in the case above, |Insert| could have special behavior with significantly better performance. Since
|
||||
it's a rare case anyway, we should just do the simplest thing that could possibly work, resolve the
|
||||
entire promise. If we measure and this turns out to show up on performance radar, we then have the
|
||||
option to fix either the callers or this mechanism.
|
||||
*/
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_AssignFromReadable(aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
// Note: not exception safe. We need something to manage temporary buffers like this
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_AssignFromElementPtrLength(buffer, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromReadable( const basic_nsAReadableString<CharT>& 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
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElementPtr( const CharT* aPtr )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElementPtrLength( const CharT* aPtr, PRUint32 aLength )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AssignFromElement( CharT aChar )
|
||||
{
|
||||
do_AssignFromReadable(basic_nsLiteralChar<CharT>(aChar));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Append()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
|
||||
do_AppendFromReadable(aReadable);
|
||||
else
|
||||
AppendFromPromise(aReadable);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::AppendFromPromise( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_AppendFromReadable(aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_AppendFromElementPtrLength(buffer, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromReadable( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
SetLength(oldLength + aReadable.Length());
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), BeginWriting(toBegin).advance( PRInt32(oldLength) ) );
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElementPtr( const CharT* aChar )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElementPtrLength( const CharT* aChar, PRUint32 aLength )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralString<CharT>(aChar, aLength));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_AppendFromElement( CharT aChar )
|
||||
{
|
||||
do_AppendFromReadable(basic_nsLiteralChar<CharT>(aChar));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Insert()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReadable )
|
||||
do_InsertFromReadable(aReadable, atPosition);
|
||||
else
|
||||
InsertFromPromise(aReadable, atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::InsertFromPromise( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_InsertFromReadable(aReadable, atPosition);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_InsertFromElementPtrLength(buffer, atPosition, length);
|
||||
delete buffer;
|
||||
}
|
||||
// else assert
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromReadable( const basic_nsAReadableString<CharT>& aReadable, PRUint32 atPosition )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
SetLength(oldLength + aReadable.Length());
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> 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)));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElementPtr( const CharT* aPtr, PRUint32 atPosition )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr), atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElementPtrLength( const CharT* aPtr, PRUint32 atPosition, PRUint32 aLength )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralString<CharT>(aPtr, aLength), atPosition);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_InsertFromElement( CharT aChar, PRUint32 atPosition )
|
||||
{
|
||||
do_InsertFromReadable(basic_nsLiteralChar<CharT>(aChar), atPosition);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Cut()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::Cut( PRUint32 cutStart, PRUint32 cutLength )
|
||||
{
|
||||
PRUint32 myLength = this->Length();
|
||||
cutLength = NS_MIN(cutLength, myLength-cutStart);
|
||||
PRUint32 cutEnd = cutStart + cutLength;
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> toBegin;
|
||||
if ( cutEnd < myLength )
|
||||
copy_string(this->BeginReading(fromBegin).advance(PRInt32(cutEnd)), this->EndReading(fromEnd), BeginWriting(toBegin).advance(PRInt32(cutStart)));
|
||||
SetLength(myLength-cutLength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// |Replace()|
|
||||
//
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
|
||||
{
|
||||
if ( NS_STATIC_CAST(const basic_nsAReadableString<CharT>*, this) != &aReplacement )
|
||||
do_ReplaceFromReadable(cutStart, cutLength, aReplacement);
|
||||
else
|
||||
ReplaceFromPromise(cutStart, cutLength, aReplacement);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::ReplaceFromPromise( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
if ( !aReadable.Promises(*this) )
|
||||
do_ReplaceFromReadable(cutStart, cutLength, aReadable);
|
||||
else
|
||||
{
|
||||
PRUint32 length = aReadable.Length();
|
||||
CharT* buffer = new CharT[length];
|
||||
if ( buffer )
|
||||
{
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = buffer;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
do_ReplaceFromReadable(cutStart, cutLength, basic_nsLiteralString<CharT>(buffer, length));
|
||||
delete buffer;
|
||||
}
|
||||
// else assert?
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void
|
||||
basic_nsAWritableString<CharT>::do_ReplaceFromReadable( PRUint32 cutStart, PRUint32 cutLength, const basic_nsAReadableString<CharT>& aReplacement )
|
||||
{
|
||||
PRUint32 oldLength = this->Length();
|
||||
|
||||
cutStart = NS_MIN(cutStart, oldLength);
|
||||
cutLength = NS_MIN(cutLength, oldLength-cutStart);
|
||||
PRUint32 cutEnd = cutStart + cutLength;
|
||||
|
||||
PRUint32 replacementLength = aReplacement.Length();
|
||||
PRUint32 replacementEnd = cutStart + replacementLength;
|
||||
|
||||
PRUint32 newLength = oldLength - cutLength + replacementLength;
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
nsWritingIterator<CharT> 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)));
|
||||
}
|
||||
|
||||
|
||||
template <class CharT>
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Mid( basic_nsAWritableString<CharT>& aResult, PRUint32 aStartPos, PRUint32 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();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
inline
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Left( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
|
||||
{
|
||||
return Mid(aResult, 0, aLengthToCopy);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
PRUint32
|
||||
basic_nsAReadableString<CharT>::Right( basic_nsAWritableString<CharT>& aResult, PRUint32 aLengthToCopy ) const
|
||||
{
|
||||
PRUint32 myLength = Length();
|
||||
aLengthToCopy = NS_MIN(myLength, aLengthToCopy);
|
||||
return Mid(aResult, myLength-aLengthToCopy, aLengthToCopy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Types
|
||||
//
|
||||
|
||||
typedef basic_nsAWritableString<PRUnichar> nsAWritableString;
|
||||
typedef basic_nsAWritableString<char> nsAWritableCString;
|
||||
|
||||
#endif // !defined(nsAWritableString_h___)
|
|
@ -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___)
|
|
@ -1,181 +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 nsBufferHandle_h___
|
||||
#define nsBufferHandle_h___
|
||||
|
||||
#include <stddef.h>
|
||||
// for |ptrdiff_t|
|
||||
|
||||
#include "prtypes.h"
|
||||
// for |PRBool|
|
||||
|
||||
#include "nsDebug.h"
|
||||
// for |NS_ASSERTION|
|
||||
|
||||
#include "nsMemory.h"
|
||||
// for |nsMemory::Free|
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsBufferHandle
|
||||
{
|
||||
public:
|
||||
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; }
|
||||
|
||||
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
|
||||
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
|
||||
|
||||
protected:
|
||||
CharT* mDataStart;
|
||||
CharT* mDataEnd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsSharedBufferHandle
|
||||
: public nsBufferHandle<CharT>
|
||||
{
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
kIsShared = 1<<31,
|
||||
kIsSingleAllocationWithBuffer = 1<<30,
|
||||
kIsStorageDefinedSeparately = 1<<29,
|
||||
|
||||
kFlagsMask = kIsShared | kIsSingleAllocationWithBuffer | kIsStorageDefinedSeparately,
|
||||
kRefCountMask = ~kFlagsMask
|
||||
};
|
||||
|
||||
public:
|
||||
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
|
||||
: nsBufferHandle<CharT>(aDataStart, aDataEnd)
|
||||
{
|
||||
mFlags = kIsShared;
|
||||
}
|
||||
|
||||
~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;
|
||||
}
|
||||
|
||||
PRBool
|
||||
IsReferenced() const
|
||||
{
|
||||
return get_refcount() != 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// need a name for this
|
||||
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; }
|
||||
|
||||
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
|
||||
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
|
||||
|
||||
protected:
|
||||
CharT* mStorageStart;
|
||||
CharT* mStorageEnd;
|
||||
};
|
||||
|
||||
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();
|
||||
nsMemory::Free(string_storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // !defined(nsBufferHandle_h___)
|
|
@ -1,105 +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 nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
// for |basic_nsAReadableString|...
|
||||
#endif
|
||||
|
||||
#include <new.h>
|
||||
// for placement |new|
|
||||
|
||||
|
||||
|
||||
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 CharT>
|
||||
HandleT*
|
||||
NS_AllocateContiguousHandleWithData( const HandleT* aDummyHandlePtr, const basic_nsAReadableString<CharT>& aDataSource, PRUint32 aAdditionalCapacity )
|
||||
{
|
||||
typedef CharT* CharT_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, CharT_ptr(0));
|
||||
|
||||
// figure out how many |CharT|s wee need to fit in the data part
|
||||
size_t data_length = aDataSource.Length();
|
||||
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(CharT);
|
||||
|
||||
|
||||
HandleT* result = 0;
|
||||
void* handle_ptr = ::operator new(handle_size + buffer_size);
|
||||
|
||||
if ( handle_ptr )
|
||||
{
|
||||
CharT* data_start_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size);
|
||||
CharT* data_end_ptr = data_start_ptr + data_length;
|
||||
CharT* buffer_end_ptr = data_start_ptr + buffer_length;
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = data_start_ptr;
|
||||
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 = CharT(0);
|
||||
|
||||
result = new (handle_ptr) HandleT(data_start_ptr, data_end_ptr, data_start_ptr, buffer_end_ptr, PR_TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !defined(nsBufferHandleUtils_h___)
|
|
@ -1,703 +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___
|
||||
|
||||
#include <ctype.h>
|
||||
// for |EOF|, |WEOF|
|
||||
|
||||
#include <string.h>
|
||||
// for |memcpy|, et al
|
||||
|
||||
#ifndef nscore_h___
|
||||
#include "nscore.h"
|
||||
// for |PRUnichar|
|
||||
#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___)
|
|
@ -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
|
|
@ -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 nsAWritableString_h___
|
||||
#include "nsAWritableString.h"
|
||||
#endif
|
||||
|
||||
#ifndef nsSharedBufferList_h___
|
||||
#include "nsSharedBufferList.h"
|
||||
#endif
|
||||
|
||||
|
||||
class nsFragmentedString
|
||||
: public basic_nsAWritableString<PRUnichar>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
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 basic_nsAReadableString<PRUnichar>& );
|
||||
// virtual void do_AppendFromReadable( const basic_nsAReadableString<PRUnichar>& );
|
||||
// virtual void do_InsertFromReadable( const basic_nsAReadableString<PRUnichar>&, PRUint32 );
|
||||
// virtual void do_ReplaceFromReadable( PRUint32, PRUint32, const basic_nsAReadableString<PRUnichar>& );
|
||||
|
||||
private:
|
||||
nsSharedBufferList mBufferList;
|
||||
};
|
||||
|
||||
#endif // !defined(nsFragmentedString_h___)
|
|
@ -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
|
||||
|
|
@ -1,93 +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___
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
|
||||
/**
|
||||
* |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 nsAReadableCString
|
||||
{
|
||||
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>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const;
|
||||
// virtual PRBool GetReadableFragment( nsReadableFragment<char>& aFragment, nsFragmentRequest aRequest ) const;
|
||||
|
||||
private:
|
||||
char* mStart;
|
||||
PRUint32 mLength;
|
||||
char mLocalBuffer[ kLocalBufferSize + 1 ];
|
||||
};
|
||||
|
||||
#endif // !defined(nsPrintfCString_h___)
|
|
@ -1,60 +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 (will be) 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.
|
||||
*/
|
||||
template <class CharT>
|
||||
class nsPrivateSharableString
|
||||
{
|
||||
public:
|
||||
virtual const nsBufferHandle<CharT>* GetBufferHandle() const;
|
||||
virtual const nsSharedBufferHandle<CharT>* GetSharedBufferHandle() const;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
const nsSharedBufferHandle<CharT>*
|
||||
nsPrivateSharableString<CharT>::GetSharedBufferHandle() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
const nsBufferHandle<CharT>*
|
||||
nsPrivateSharableString<CharT>::GetBufferHandle() const
|
||||
{
|
||||
return GetSharedBufferHandle();
|
||||
}
|
||||
|
||||
#endif // !defined(nsPrivateSharableString_h___)
|
|
@ -1,593 +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"
|
||||
|
||||
|
||||
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 nsAReadableString& aSource, nsAWritableCString& 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 nsAReadableCString& aSource, nsAWritableString& 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 FromCharT, class ToCharT>
|
||||
inline
|
||||
ToCharT*
|
||||
AllocateStringCopy( const basic_nsAReadableString<FromCharT>& aSource, ToCharT* )
|
||||
{
|
||||
return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
|
||||
}
|
||||
|
||||
|
||||
NS_COM
|
||||
char*
|
||||
ToNewCString( const nsAReadableString& 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 nsAReadableString& 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 nsAReadableCString& 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 nsAReadableString& 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 nsAReadableCString& 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 nsAReadableString& 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,
|
||||
nsAWritableString& 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,
|
||||
nsAWritableString& 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 nsAReadableString& 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( nsAWritableString& aString )
|
||||
{
|
||||
nsAWritableString::iterator fromBegin, fromEnd;
|
||||
ConvertToUpperCase<PRUnichar> converter;
|
||||
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToUpperCase( nsAWritableCString& aCString )
|
||||
{
|
||||
nsAWritableCString::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( nsAWritableString& aString )
|
||||
{
|
||||
nsAWritableString::iterator fromBegin, fromEnd;
|
||||
ConvertToLowerCase<PRUnichar> converter;
|
||||
copy_string(aString.BeginWriting(fromBegin), aString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
void
|
||||
ToLowerCase( nsAWritableCString& aCString )
|
||||
{
|
||||
nsAWritableCString::iterator fromBegin, fromEnd;
|
||||
ConvertToLowerCase<char> converter;
|
||||
copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
|
||||
}
|
||||
|
||||
|
||||
template <class CharT>
|
||||
inline // probably wishful thinking
|
||||
PRBool
|
||||
FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
|
||||
nsReadingIterator<CharT>& aSearchStart,
|
||||
nsReadingIterator<CharT>& aSearchEnd )
|
||||
{
|
||||
PRBool found_it = PR_FALSE;
|
||||
|
||||
// only bother searching at all if we're given a non-empty range to search
|
||||
if ( aSearchStart != aSearchEnd )
|
||||
{
|
||||
nsReadingIterator<CharT> 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 && *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
|
||||
nsReadingIterator<CharT> testPattern(aPatternStart);
|
||||
nsReadingIterator<CharT> 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 ( *testPattern != *testSearch )
|
||||
{
|
||||
++aSearchStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found_it;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRBool
|
||||
FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
|
||||
{
|
||||
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRBool
|
||||
FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
|
||||
{
|
||||
return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template <class CharT>
|
||||
inline // probably wishful thinking
|
||||
PRBool
|
||||
RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern,
|
||||
nsReadingIterator<CharT>& aSearchStart,
|
||||
nsReadingIterator<CharT>& aSearchEnd )
|
||||
{
|
||||
PRBool found_it = PR_FALSE;
|
||||
|
||||
nsReadingIterator<CharT> savedSearchEnd(aSearchEnd);
|
||||
nsReadingIterator<CharT> 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 nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
|
||||
{
|
||||
return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRBool
|
||||
RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
|
||||
{
|
||||
return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class CharT>
|
||||
inline // probably wishful thinking
|
||||
PRBool
|
||||
FindCharInReadable_Impl( CharT aChar,
|
||||
nsReadingIterator<CharT>& aSearchStart,
|
||||
nsReadingIterator<CharT>& aSearchEnd )
|
||||
{
|
||||
while ( aSearchStart != aSearchEnd )
|
||||
{
|
||||
PRInt32 fragmentLength;
|
||||
if ( SameFragment(aSearchStart, aSearchEnd) )
|
||||
fragmentLength = aSearchEnd.get() - aSearchStart.get();
|
||||
else
|
||||
fragmentLength = aSearchStart.size_forward();
|
||||
|
||||
const CharT* charFoundAt = nsCharTraits<CharT>::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( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd )
|
||||
{
|
||||
return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRBool
|
||||
FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd )
|
||||
{
|
||||
return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
PRUint32
|
||||
CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr,
|
||||
CharT aChar )
|
||||
{
|
||||
PRUint32 count = 0;
|
||||
nsReadingIterator<CharT> begin, end;
|
||||
|
||||
aStr.BeginReading(begin);
|
||||
aStr.EndReading(end);
|
||||
|
||||
while (begin != end) {
|
||||
if (*begin == aChar) {
|
||||
count++;
|
||||
}
|
||||
begin++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRUint32
|
||||
CountCharInReadable( const nsAReadableString& aStr,
|
||||
PRUnichar aChar )
|
||||
{
|
||||
return CountCharInReadable_Impl(aStr, aChar);
|
||||
}
|
||||
|
||||
NS_COM
|
||||
PRUint32
|
||||
CountCharInReadable( const nsAReadableCString& aStr,
|
||||
char aChar )
|
||||
{
|
||||
return CountCharInReadable_Impl(aStr, aChar);
|
||||
}
|
|
@ -1,217 +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 nsAWritableString_h___
|
||||
#include "nsAWritableString.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 nsAReadableString& aSource, nsAWritableCString& aDest );
|
||||
NS_COM void CopyASCIItoUCS2( const nsAReadableCString& aSource, nsAWritableString& 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 nsAReadableString& 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 nsAReadableCString& 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 nsAReadableString& 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 nsAReadableString& 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 nsAReadableCString& 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 nsAReadableString& 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,
|
||||
nsAWritableString& 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,
|
||||
nsAWritableString& 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 nsAReadableString& aString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts case in place in the argument string.
|
||||
*/
|
||||
NS_COM void ToUpperCase( nsAWritableString& );
|
||||
NS_COM void ToUpperCase( nsAWritableCString& );
|
||||
|
||||
NS_COM void ToLowerCase( nsAWritableString& );
|
||||
NS_COM void ToLowerCase( nsAWritableCString& );
|
||||
|
||||
/**
|
||||
* 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; we can implement that later.
|
||||
*/
|
||||
NS_COM PRBool FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
|
||||
NS_COM PRBool FindInReadable( const nsAReadableCString& 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; we can implement that later.
|
||||
*/
|
||||
NS_COM PRBool RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& );
|
||||
NS_COM PRBool RFindInReadable( const nsAReadableCString& 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>&, nsReadingIterator<PRUnichar>& );
|
||||
NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>&, nsReadingIterator<char>& );
|
||||
|
||||
/**
|
||||
* Finds the number of occurences of |aChar| in the string |aStr|
|
||||
*/
|
||||
NS_COM PRUint32 CountCharInReadable( const nsAReadableString& aStr,
|
||||
PRUnichar aChar );
|
||||
NS_COM PRUint32 CountCharInReadable( const nsAReadableCString& aStr,
|
||||
char aChar );
|
||||
|
||||
#endif // !defined(nsReadableUtils_h___)
|
|
@ -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
|
|
@ -1,221 +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 nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
// for |nsReadingIterator|
|
||||
#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), NS_READABLE_CAST(PRUnichar, nsLiteralString(aData, aDataLength)), aAdditionalCapacity);
|
||||
}
|
||||
|
||||
static
|
||||
Buffer*
|
||||
NewSingleAllocationBuffer( const nsAReadableString& 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___)
|
|
@ -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 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.
|
||||
*
|
||||
* Original Author:
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsSharedString_h___
|
||||
#define nsSharedString_h___
|
||||
|
||||
#ifndef nsAReadableString_h___
|
||||
#include "nsAReadableString.h"
|
||||
#endif
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsSharedString
|
||||
: public basic_nsAReadableString<CharT>
|
||||
/*
|
||||
...
|
||||
*/
|
||||
{
|
||||
public:
|
||||
basic_nsSharedString( const CharT* data, size_t length )
|
||||
: mRefCount(0), mData(data), mLength(length)
|
||||
{
|
||||
// nothing else to do here
|
||||
}
|
||||
|
||||
private:
|
||||
~basic_nsSharedString() { } // You can't sub-class me, or make an instance of me on the stack
|
||||
|
||||
// NOT TO BE IMPLEMENTED
|
||||
// we're reference counted, remember. copying and passing by value are wrong
|
||||
// basic_nsSharedString(); // we define at least one constructor, so the default constructor will not be auto-generated. It's wrong to create me with no data anyway
|
||||
basic_nsSharedString( const basic_nsSharedString<CharT>& ); // copy-constructor, the auto generated one would reference somebody elses data
|
||||
void operator=( const basic_nsSharedString<CharT>& ); // copy-assignment operator
|
||||
|
||||
// operator delete?
|
||||
|
||||
public:
|
||||
|
||||
virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const;
|
||||
|
||||
virtual
|
||||
PRUint32
|
||||
Length() const
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
AddRef() const
|
||||
{
|
||||
return ++mRefCount;
|
||||
}
|
||||
|
||||
nsrefcnt
|
||||
Release() const
|
||||
{
|
||||
nsrefcnt result = --mRefCount;
|
||||
if ( !mRefCount )
|
||||
{
|
||||
// would have to call my destructor by hand here, if there was anything to destruct
|
||||
operator delete(this); // form of |delete| should always match the |new|
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable nsrefcnt mRefCount;
|
||||
const CharT* mData;
|
||||
size_t mLength;
|
||||
};
|
||||
|
||||
NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsSharedString<CharT>, CharT)
|
||||
|
||||
template <class CharT>
|
||||
const CharT*
|
||||
basic_nsSharedString<CharT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 anOffset ) const
|
||||
{
|
||||
switch ( aRequest )
|
||||
{
|
||||
case kFirstFragment:
|
||||
case kLastFragment:
|
||||
case kFragmentAt:
|
||||
aFragment.mEnd = (aFragment.mStart = mData) + mLength;
|
||||
return aFragment.mStart + anOffset;
|
||||
|
||||
case kPrevFragment:
|
||||
case kNextFragment:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class CharT>
|
||||
class basic_nsSharedStringPtr
|
||||
{
|
||||
public:
|
||||
// default constructor
|
||||
basic_nsSharedStringPtr() : mRawPtr(0) { }
|
||||
|
||||
// copy-constructor
|
||||
basic_nsSharedStringPtr( const basic_nsSharedStringPtr<CharT>& rhs )
|
||||
: mRawPtr(rhs.mRawPtr)
|
||||
{
|
||||
mRawPtr->AddRef();
|
||||
}
|
||||
|
||||
~basic_nsSharedStringPtr()
|
||||
{
|
||||
if ( mRawPtr )
|
||||
mRawPtr->Release();
|
||||
}
|
||||
|
||||
// copy-assignment operator
|
||||
basic_nsSharedStringPtr<CharT>&
|
||||
operator=( const basic_nsSharedStringPtr<CharT>& );
|
||||
|
||||
basic_nsSharedString<CharT>*
|
||||
operator->() const
|
||||
{
|
||||
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
|
||||
return mRawPtr;
|
||||
}
|
||||
|
||||
basic_nsSharedString<CharT>&
|
||||
operator*() const
|
||||
{
|
||||
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL string pointer with operator->().");
|
||||
return *mRawPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
const basic_nsSharedString<CharT>* mRawPtr;
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
basic_nsSharedStringPtr<CharT>&
|
||||
basic_nsSharedStringPtr<CharT>::operator=( const basic_nsSharedStringPtr<CharT>& rhs )
|
||||
// Not |inline|
|
||||
{
|
||||
if ( rhs.mRawPtr )
|
||||
rhs.mRawPtr->AddRef();
|
||||
basic_nsSharedString<CharT>* oldPtr = mRawPtr;
|
||||
mRawPtr = rhs.mRawPtr;
|
||||
if ( oldPtr )
|
||||
oldPtr->Release();
|
||||
}
|
||||
|
||||
|
||||
template <class CharT>
|
||||
basic_nsSharedString<CharT>*
|
||||
new_nsSharedString( const basic_nsAReadableString<CharT>& aReadable )
|
||||
{
|
||||
size_t object_size = ((sizeof(basic_nsSharedString<CharT>) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
|
||||
size_t string_length = aReadable.Length();
|
||||
size_t string_size = string_length * sizeof(CharT);
|
||||
|
||||
void* object_ptr = operator new(object_size + string_size);
|
||||
if ( object_ptr )
|
||||
{
|
||||
typedef CharT* CharT_ptr;
|
||||
CharT* string_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
|
||||
|
||||
nsReadingIterator<CharT> fromBegin, fromEnd;
|
||||
CharT* toBegin = string_ptr;
|
||||
copy_string(aReadable.BeginReading(fromBegin), aReadable.EndReading(fromEnd), toBegin);
|
||||
return new (object_ptr) basic_nsSharedString<CharT>(string_ptr, string_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef basic_nsSharedString<PRUnichar> nsSharedString;
|
||||
typedef basic_nsSharedString<char> nsSharedCString;
|
||||
|
||||
typedef basic_nsSharedStringPtr<PRUnichar> nsSharedStringPtr;
|
||||
typedef basic_nsSharedStringPtr<char> nsSharedCStringPtr;
|
||||
|
||||
|
||||
#endif // !defined(nsSharedString_h___)
|
|
@ -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 nsAReadableString& 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 nsAReadableString& 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 nsAReadableString& 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 nsAReadableString& 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);
|
||||
}
|
|
@ -1,196 +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___
|
||||
|
||||
#include "nsAReadableString.h"
|
||||
#include "nsSharedBufferList.h"
|
||||
|
||||
|
||||
/**
|
||||
* 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 nsPromiseReadable<PRUnichar>
|
||||
{
|
||||
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 nsAReadableString& );
|
||||
// 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 nsAReadableString& );
|
||||
|
||||
~nsSlidingSubstring();
|
||||
|
||||
virtual PRUint32 Length() const { return mLength; }
|
||||
|
||||
protected:
|
||||
nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList );
|
||||
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
|
||||
|
||||
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 nsPromiseReadable<PRUnichar>,
|
||||
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;
|
||||
|
||||
void InsertReadable( const nsAReadableString&, 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___)
|
|
@ -1,923 +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.
|
||||
*
|
||||
* Original Author:
|
||||
* Rick Gessner <rickg@netscape.com>
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Collins <scc@mozilla.org>
|
||||
*/
|
||||
|
||||
/******************************************************************************************
|
||||
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.
|
||||
|
||||
*******************************************************************************************/
|
||||
|
||||
#include "nsStr.h"
|
||||
#include "bufferRoutines.h"
|
||||
#include <stdio.h> //only used for printf
|
||||
#include "nsCRT.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
//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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
523
xpcom/ds/nsStr.h
523
xpcom/ds/nsStr.h
|
@ -1,523 +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>
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
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.
|
||||
|
||||
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#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
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,584 +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>
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _nsCString_
|
||||
#define _nsCString_
|
||||
|
||||
#include "nsString2.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
#include <stdio.h>
|
||||
#include "nsStr.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
|
||||
class NS_COM nsSubsumeCStr;
|
||||
|
||||
class NS_COM nsCString :
|
||||
public nsAWritableCString,
|
||||
public nsStr {
|
||||
|
||||
protected:
|
||||
virtual const void* Implementation() const { return "nsCString"; }
|
||||
virtual const char* GetReadableFragment( nsReadableFragment<char>&, nsFragmentRequest, PRUint32 ) const;
|
||||
virtual char* GetWritableFragment( nsWritableFragment<char>&, nsFragmentRequest, PRUint32 );
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsCString();
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsCString
|
||||
*/
|
||||
nsCString(const nsCString& aString);
|
||||
|
||||
explicit nsCString( const nsAReadableCString& );
|
||||
|
||||
explicit nsCString(const char*);
|
||||
nsCString(const char*, PRInt32);
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
explicit nsCString(nsSubsumeCStr& aSubsumeStr);
|
||||
|
||||
/**
|
||||
* 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...
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve const ptr to internal buffer; DO NOT TRY TO FREE IT!
|
||||
*/
|
||||
const char* GetBuffer() const { return get(); } // to be deprecated, prefer |get()|
|
||||
|
||||
const char* get() const { return mStr; }
|
||||
|
||||
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...
|
||||
*********************************************************************/
|
||||
//#ifndef STANDALONE_STRING_TESTS
|
||||
operator char*() {return mStr;}
|
||||
operator const char*() const {return (const char*)mStr;}
|
||||
//#endif
|
||||
|
||||
/**
|
||||
* 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 Recycle().
|
||||
* @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 Recycle().
|
||||
* @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 nsAReadableCString& 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 nsAReadableString& 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 nsAReadableString& 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 );
|
||||
|
||||
virtual void do_AppendFromReadable( const nsAReadableCString& );
|
||||
|
||||
void InsertWithConversion(PRUnichar aChar,PRUint32 anOffset);
|
||||
// Why no |InsertWithConversion(PRUnichar*)|?
|
||||
|
||||
virtual void do_InsertFromReadable( const nsAReadableCString&, PRUint32 );
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
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;
|
||||
|
||||
PRBool EqualsIgnoreCase(const char* aString,PRInt32 aCount=-1) const;
|
||||
PRBool EqualsIgnoreCase(const PRUnichar* aString,PRInt32 aCount=-1) const;
|
||||
|
||||
|
||||
void DebugDump(void) const;
|
||||
|
||||
|
||||
static void Recycle(nsCString* aString);
|
||||
static nsCString* CreateString(void);
|
||||
|
||||
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 nsAReadableCString& aString);
|
||||
explicit nsCAutoString(const char* aString);
|
||||
nsCAutoString(const char* aString,PRInt32 aLength);
|
||||
explicit nsCAutoString(const CBufDescriptor& aBuffer);
|
||||
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsCAutoString(const nsSubsumeCStr& aSubsumeStr); // AIX and VAC++ require a const
|
||||
#else
|
||||
explicit nsCAutoString(nsSubsumeCStr& aSubsumeStr);
|
||||
#endif // AIX || XP_OS2_VACPP
|
||||
|
||||
|
||||
nsCAutoString& operator=( const nsCAutoString& aString ) { Assign(aString); return *this; }
|
||||
private:
|
||||
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
|
||||
public:
|
||||
nsCAutoString& operator=( const nsAReadableCString& 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 nsAReadableString& aString );
|
||||
|
||||
const char* get() const
|
||||
{
|
||||
return mStr;
|
||||
}
|
||||
|
||||
operator const char*() const // to be deprecated, prefer |get()|
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
protected:
|
||||
void Append( const PRUnichar* aString, PRUint32 aLength );
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
NS_ConvertUCS2toUTF8( char );
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************
|
||||
The subsumestr class is very unusual.
|
||||
It differs from a normal string in that it doesn't use normal
|
||||
copy semantics when another string is assign to this.
|
||||
Instead, it "steals" the contents of the source string.
|
||||
|
||||
This is very handy for returning nsString classes as part of
|
||||
an operator+(...) for example, in that it cuts down the number
|
||||
of copy operations that must occur.
|
||||
|
||||
You should probably not use this class unless you really know
|
||||
what you're doing.
|
||||
***************************************************************/
|
||||
class NS_COM nsSubsumeCStr : public nsCString {
|
||||
public:
|
||||
explicit nsSubsumeCStr(nsStr& aString);
|
||||
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
|
||||
nsSubsumeCStr& operator=( const nsSubsumeCStr& aString ) { Assign(aString); return *this; }
|
||||
nsSubsumeCStr& operator=( const nsAReadableCString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeCStr& operator=( const nsPromiseReadable<char>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeCStr& operator=( const char* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsSubsumeCStr& operator=( char aChar ) { Assign(aChar); return *this; }
|
||||
private:
|
||||
void operator=( PRUnichar ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,693 +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>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
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
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _nsString_
|
||||
#define _nsString_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
#include <stdio.h>
|
||||
#include "nsString.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsStr.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
#include "nsAWritableString.h"
|
||||
|
||||
#ifdef STANDALONE_MI_STRING_TESTS
|
||||
class nsAReadableString { public: virtual ~nsAReadableString() { } };
|
||||
class nsAWritableString : public nsAReadableString { public: virtual ~nsAWritableString() { } };
|
||||
#endif
|
||||
|
||||
class nsISizeOfHandler;
|
||||
|
||||
|
||||
#define nsString2 nsString
|
||||
#define nsAutoString2 nsAutoString
|
||||
|
||||
class NS_COM nsSubsumeStr;
|
||||
|
||||
class NS_COM nsString :
|
||||
public nsAWritableString,
|
||||
public nsStr {
|
||||
|
||||
protected:
|
||||
virtual const void* Implementation() const { return "nsString"; }
|
||||
virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const;
|
||||
virtual PRUnichar* GetWritableFragment( nsWritableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 );
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
nsString();
|
||||
|
||||
/**
|
||||
* This is our copy constructor
|
||||
* @param reference to another nsString
|
||||
*/
|
||||
nsString(const nsString& aString);
|
||||
|
||||
explicit nsString(const nsAReadableString&);
|
||||
|
||||
explicit nsString(const PRUnichar*);
|
||||
nsString(const PRUnichar*, PRInt32);
|
||||
|
||||
|
||||
/**
|
||||
* This constructor takes a subsumestr
|
||||
* @param reference to subsumestr
|
||||
*/
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ require a const here
|
||||
#else
|
||||
explicit nsString(nsSubsumeStr& aSubsumeStr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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;
|
||||
const PRUnichar* GetUnicode(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 Recycle().
|
||||
* @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 Recycle().
|
||||
* @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 Recycle().
|
||||
* @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 nsAReadableString& 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);
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
static void Recycle(nsString* aString);
|
||||
static nsString* CreateString(void);
|
||||
|
||||
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 nsAReadableString& 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);
|
||||
|
||||
#if defined(AIX) || defined(XP_OS2_VACPP)
|
||||
explicit nsAutoString(const nsSubsumeStr& aSubsumeStr); // AIX and VAC++ requires a const
|
||||
#else
|
||||
explicit nsAutoString(nsSubsumeStr& aSubsumeStr);
|
||||
#endif // AIX || XP_OS2_VACPP
|
||||
|
||||
|
||||
nsAutoString& operator=( const nsAutoString& aString ) { Assign(aString); return *this; }
|
||||
private:
|
||||
void operator=( char ); // NOT TO BE IMPLEMENTED
|
||||
public:
|
||||
nsAutoString& operator=( const nsAReadableString& 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 char* );
|
||||
NS_ConvertASCIItoUCS2( const char*, PRUint32 );
|
||||
explicit NS_ConvertASCIItoUCS2( char );
|
||||
|
||||
const PRUnichar* get() const { return GetUnicode(); }
|
||||
|
||||
operator const PRUnichar*() const
|
||||
{
|
||||
return GetUnicode();
|
||||
}
|
||||
|
||||
operator nsLiteralString() const
|
||||
{
|
||||
return nsLiteralString(mUStr, mLength);
|
||||
}
|
||||
|
||||
private:
|
||||
// NOT TO BE IMPLEMENTED
|
||||
NS_ConvertASCIItoUCS2( PRUnichar );
|
||||
};
|
||||
|
||||
#define NS_ConvertToString NS_ConvertASCIItoUCS2
|
||||
|
||||
#if 0
|
||||
inline
|
||||
nsAutoString
|
||||
NS_ConvertToString( const char* aCString )
|
||||
{
|
||||
nsAutoString result;
|
||||
result.AssignWithConversion(aCString);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
nsAutoString
|
||||
NS_ConvertToString( const char* aCString, PRUint32 aLength )
|
||||
{
|
||||
nsAutoString result;
|
||||
result.AssignWithConversion(aCString, aLength);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
class NS_COM NS_ConvertUTF8toUCS2
|
||||
: public nsAutoString
|
||||
{
|
||||
public:
|
||||
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 );
|
||||
}
|
||||
|
||||
operator const PRUnichar*() const
|
||||
{
|
||||
return GetUnicode();
|
||||
}
|
||||
|
||||
protected:
|
||||
void Init( const char* aCString, PRUint32 aLength );
|
||||
|
||||
private:
|
||||
NS_ConvertUTF8toUCS2( PRUnichar );
|
||||
};
|
||||
|
||||
/***************************************************************
|
||||
The subsumestr class is very unusual.
|
||||
It differs from a normal string in that it doesn't use normal
|
||||
copy semantics when another string is assign to this.
|
||||
Instead, it "steals" the contents of the source string.
|
||||
|
||||
This is very handy for returning nsString classes as part of
|
||||
an operator+(...) for example, in that it cuts down the number
|
||||
of copy operations that must occur.
|
||||
|
||||
You should probably not use this class unless you really know
|
||||
what you're doing.
|
||||
***************************************************************/
|
||||
class NS_COM nsSubsumeStr : public nsString {
|
||||
public:
|
||||
nsSubsumeStr();
|
||||
explicit nsSubsumeStr(nsStr& aString);
|
||||
nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
int Subsume(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
|
||||
|
||||
nsSubsumeStr& operator=( const nsSubsumeStr& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const nsAReadableString& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const nsPromiseReadable<PRUnichar>& aReadable ) { Assign(aReadable); return *this; }
|
||||
nsSubsumeStr& operator=( const PRUnichar* aPtr ) { Assign(aPtr); return *this; }
|
||||
nsSubsumeStr& operator=( PRUnichar aChar ) { Assign(aChar); return *this; }
|
||||
private:
|
||||
void operator=( char ); // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,163 +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 (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
PRUnichar*
|
||||
nsXPIDLString::Copy(const PRUnichar* aString)
|
||||
{
|
||||
NS_ASSERTION(aString, "null ptr");
|
||||
if (! aString)
|
||||
return 0;
|
||||
|
||||
PRInt32 len = 0;
|
||||
|
||||
{
|
||||
const PRUnichar* p = aString;
|
||||
while (*p++)
|
||||
len++;
|
||||
}
|
||||
|
||||
PRUnichar* result = XPIDL_STRING_ALLOC(len + 1);
|
||||
if (result) {
|
||||
PRUnichar* q = result;
|
||||
while (*aString) {
|
||||
*q = *aString;
|
||||
q++;
|
||||
aString++;
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PRUnichar**
|
||||
nsXPIDLString::StartAssignmentByValue()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_TRUE;
|
||||
return &mBuf;
|
||||
}
|
||||
|
||||
|
||||
const PRUnichar**
|
||||
nsXPIDLString::StartAssignmentByReference()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
return (const PRUnichar**) &mBuf;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsXPIDLCString
|
||||
|
||||
nsXPIDLCString::~nsXPIDLCString()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
}
|
||||
|
||||
|
||||
nsXPIDLCString& nsXPIDLCString::operator =(const char* aCString)
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
if (aCString) {
|
||||
mBuf = Copy(aCString);
|
||||
mBufOwner = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsXPIDLCString::Copy(const char* aCString)
|
||||
{
|
||||
NS_ASSERTION(aCString, "null ptr");
|
||||
if (! aCString)
|
||||
return 0;
|
||||
|
||||
PRInt32 len = PL_strlen(aCString);
|
||||
char* result = XPIDL_CSTRING_ALLOC(len + 1);
|
||||
if (result)
|
||||
PL_strcpy(result, aCString);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char**
|
||||
nsXPIDLCString::StartAssignmentByValue()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_TRUE;
|
||||
return &mBuf;
|
||||
}
|
||||
|
||||
|
||||
const char**
|
||||
nsXPIDLCString::StartAssignmentByReference()
|
||||
{
|
||||
if (mBufOwner && mBuf)
|
||||
XPIDL_FREE(mBuf);
|
||||
|
||||
mBuf = 0;
|
||||
mBufOwner = PR_FALSE;
|
||||
return (const char**) &mBuf;
|
||||
}
|
||||
|
||||
|
|
@ -1,382 +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):
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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 either `getter_Copies()' or
|
||||
`getter_Shares()' 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 of `getter_Shares()', the
|
||||
callee is returning a const reference to `the real deal' (this can
|
||||
be done using the [shared] attribute in XPIDL).
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsXPIDLString_h__
|
||||
#define nsXPIDLString_h__
|
||||
|
||||
#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()| and
|
||||
// |getter_Shares()| helper functions, this can be used instead of
|
||||
// the "naked" |PRUnichar*| interface for |wstring| parameters in
|
||||
// XPIDL interfaces.
|
||||
//
|
||||
|
||||
class NS_COM nsXPIDLString {
|
||||
private:
|
||||
PRUnichar* mBuf;
|
||||
PRBool mBufOwner;
|
||||
|
||||
PRUnichar** StartAssignmentByValue();
|
||||
const PRUnichar** StartAssignmentByReference();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new, uninitialized wrapper for a Unicode string.
|
||||
*/
|
||||
nsXPIDLString() : mBuf(0), mBufOwner(PR_FALSE) {}
|
||||
|
||||
virtual ~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; }
|
||||
|
||||
/**
|
||||
* Make a copy of the Unicode string. Use this function in the
|
||||
* callee to ensure that the correct memory allocator is used.
|
||||
*/
|
||||
static PRUnichar* Copy(const PRUnichar* aString);
|
||||
|
||||
// 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;
|
||||
|
||||
// A helper class for assignment-by-reference. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterShares {
|
||||
private:
|
||||
nsXPIDLString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterShares(nsXPIDLString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator const PRUnichar**() {
|
||||
return mXPIDLString.StartAssignmentByReference();
|
||||
}
|
||||
|
||||
friend GetterShares getter_Shares(nsXPIDLString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterShares;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLString object that is to
|
||||
* receive a |[shared] out| value.
|
||||
*/
|
||||
inline nsXPIDLString::GetterShares
|
||||
getter_Shares(nsXPIDLString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLString::GetterShares(aXPIDLString);
|
||||
}
|
||||
|
||||
|
||||
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
|
||||
inline
|
||||
PRBool
|
||||
operator==(const PRUnichar* lhs, const nsXPIDLString& rhs)
|
||||
{
|
||||
return lhs == NS_STATIC_CAST(const PRUnichar*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLString& lhs, const PRUnichar* rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const PRUnichar*, lhs) == 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()| and
|
||||
// |getter_Shares()| helper functions, this can be used instead of
|
||||
// the "naked" |char*| interface for |string| parameters in XPIDL
|
||||
// interfaces.
|
||||
//
|
||||
|
||||
class NS_COM nsXPIDLCString {
|
||||
private:
|
||||
char* mBuf;
|
||||
PRBool mBufOwner;
|
||||
|
||||
char** StartAssignmentByValue();
|
||||
const char** StartAssignmentByReference();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new, uninitialized wrapper for a single-byte string.
|
||||
*/
|
||||
nsXPIDLCString() : mBuf(0), mBufOwner(PR_FALSE) {}
|
||||
|
||||
virtual ~nsXPIDLCString();
|
||||
|
||||
/**
|
||||
* Assign a single-byte string to this wrapper. Copies
|
||||
* and owns the result.
|
||||
*/
|
||||
nsXPIDLCString& operator=(const char* aString);
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
/**
|
||||
* Make a copy of the single-byte string. Use this function in the
|
||||
* callee to ensure that the correct memory allocator is used.
|
||||
*/
|
||||
static char* Copy(const char* aString);
|
||||
|
||||
// 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;
|
||||
|
||||
// A helper class for assignment-by-reference. This class is an
|
||||
// implementation detail and should not be considered part of the
|
||||
// public interface.
|
||||
class NS_COM GetterShares {
|
||||
private:
|
||||
nsXPIDLCString& mXPIDLString;
|
||||
|
||||
public:
|
||||
GetterShares(nsXPIDLCString& aXPIDLString)
|
||||
: mXPIDLString(aXPIDLString) {}
|
||||
|
||||
operator const char**() {
|
||||
return mXPIDLString.StartAssignmentByReference();
|
||||
}
|
||||
|
||||
friend GetterShares getter_Shares(nsXPIDLCString& aXPIDLString);
|
||||
};
|
||||
|
||||
friend class GetterShares;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use this function to "wrap" the nsXPIDLCString object that is to
|
||||
* receive a |[shared] out| value.
|
||||
*/
|
||||
inline nsXPIDLCString::GetterShares
|
||||
getter_Shares(nsXPIDLCString& aXPIDLString)
|
||||
{
|
||||
return nsXPIDLCString::GetterShares(aXPIDLString);
|
||||
}
|
||||
|
||||
// XXX THESE ARE NOT strcmp()! DON'T TRY TO USE THEM AS SUCH!
|
||||
inline
|
||||
PRBool
|
||||
operator==(const char* lhs, const nsXPIDLCString& rhs)
|
||||
{
|
||||
return lhs == NS_STATIC_CAST(const char*, rhs);
|
||||
}
|
||||
|
||||
inline
|
||||
PRBool
|
||||
operator==(const nsXPIDLCString& lhs, const char* rhs)
|
||||
{
|
||||
return NS_STATIC_CAST(const char*, lhs) == 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__
|
Загрузка…
Ссылка в новой задаче