summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp1327
1 files changed, 1327 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
new file mode 100644
index 00000000..76106a27
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
@@ -0,0 +1,1327 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsString.h"
+
+
+ /**
+ * nsTString obsolete API support
+ */
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+
+#include "nsDependentString.h"
+#include "nsDependentSubstring.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsUTF8Utils.h"
+#include "prdtoa.h"
+#include "prprf.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+/* ***** BEGIN RICKG BLOCK *****
+ *
+ * NOTE: This section of code was extracted from rickg's bufferRoutines.h file.
+ * For the most part it remains unmodified. We want to eliminate (or at
+ * least clean up) this code at some point. If you find the formatting
+ * in this section somewhat inconsistent, don't blame me! ;-)
+ */
+
+// XXXdarin what is wrong with STDC's tolower?
+inline char
+ascii_tolower(char aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z')
+ return aChar + ('a' - 'A');
+ return aChar;
+}
+
+//-----------------------------------------------------------------------------
+//
+// 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 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)
+ */
+static PRInt32
+FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,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;
+
+ 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 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)
+ */
+static PRInt32
+FindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,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 = aDest;
+ const PRUnichar* left = root+anOffset;
+ const PRUnichar* last = left+aCount;
+ const PRUnichar* max = root+aDestLength;
+ const PRUnichar* end = (last<max) ? last : max;
+
+ 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 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)
+ */
+
+static PRInt32
+RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((aChar<256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ //We'll only search if the given aChar is within the normal ascii a range,
+ //(Since this string is definitely within the ascii range).
+
+ if(0 < aCount) {
+
+ const char* rightmost = aDest + anOffset;
+ const char* min = rightmost - aCount + 1;
+ const char* leftmost = (min<aDest) ? aDest: min;
+
+ 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 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)
+ */
+static PRInt32
+RFindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ if(0 < aCount) {
+
+ const PRUnichar* root = aDest;
+ const PRUnichar* rightmost = root + anOffset;
+ const PRUnichar* min = rightmost - aCount + 1;
+ const PRUnichar* leftmost = (min<root) ? root: min;
+
+ while(leftmost <= rightmost){
+
+ if((*rightmost) == aChar)
+ return rightmost - root;
+
+ --rightmost;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+//-----------------------------------------------------------------------------
+//
+// 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 <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ PRInt32 result=0;
+ if(aIgnoreCase)
+ result=PRInt32(PL_strncasecmp(aStr1, aStr2, aCount));
+ else
+ result=nsCharTraits<char>::compare(aStr1,aStr2,aCount);
+
+ // alien comparisons may return out-of-bound answers
+ // instead of the -1, 0, 1 expected by most clients
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ 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 <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To2(const PRUnichar* aStr1,const PRUnichar* aStr2,PRUint32 aCount){
+ PRInt32 result;
+
+ if ( aStr1 && aStr2 )
+ result = nsCharTraits<PRUnichar>::compare(aStr1, aStr2, aCount);
+
+ // The following cases are rare and survivable caller errors.
+ // Two null pointers are equal, but any string, even 0 length
+ // is greater than a null pointer. It might not really matter,
+ // but we pick something reasonable anyway.
+ else if ( !aStr1 && !aStr2 )
+ result = 0;
+ else if ( aStr1 )
+ result = 1;
+ else
+ result = -1;
+
+ // alien comparisons may give answers outside the -1, 0, 1 expected by callers
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ 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 <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To1(const PRUnichar* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ const PRUnichar* s1 = aStr1;
+ const char *s2 = aStr2;
+
+ if (aStr1 && aStr2) {
+ if (aCount != 0) {
+ do {
+
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = PRUnichar((unsigned char)*s2++);
+
+ if (c1 != c2) {
+#ifdef NS_DEBUG
+ // we won't warn on c1>=128 (the 2-byte value) because often
+ // it is just fine to compare an constant, ascii value (i.e. "body")
+ // against some non-ascii value (i.e. a unicode string that
+ // was downloaded from a web page)
+ if (aIgnoreCase && c2>=128)
+ NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!");
+#endif
+
+ // can't do case conversion on characters out of our range
+ if (aIgnoreCase && c1<128 && c2<128) {
+
+ c1 = ascii_tolower(char(c1));
+ c2 = ascii_tolower(char(c2));
+
+ if (c1 == c2) continue;
+ }
+
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ } while (--aCount);
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * 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 <,==,>
+ */
+inline PRInt32
+Compare1To2(const char* aStr1,const PRUnichar* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// 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
+ */
+static 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,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,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
+ */
+static PRInt32
+CompressChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ PRUnichar* from = 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,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ break;
+ }
+ } //while
+ } //if
+ } //if
+ *to = 0;
+ }
+ return to - (PRUnichar*)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
+ */
+static PRInt32
+StripChars1(char* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ 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,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
+ */
+static PRInt32
+StripChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ PRUnichar* to = aString;
+ PRUnichar* from = 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,aSetLen))){
+ *to++ = theChar;
+ }
+ }
+ *to = 0;
+ }
+ return to - (PRUnichar*)aString;
+}
+
+/* ***** END RICKG BLOCK ***** */
+
+static const char* kWhitespace="\b\t\r\n ";
+
+// This function is used to implement FindCharInSet and friends
+template <class CharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+CharT
+GetFindInSetFilter( const CharT* set)
+ {
+ CharT filter = ~CharT(0); // All bits set
+ while (*set) {
+ filter &= ~(*set);
+ ++set;
+ }
+ return filter;
+ }
+
+// This template class is used by our code to access rickg's buffer routines.
+template <class CharT> struct nsBufferRoutines {};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<char>
+ {
+ static
+ PRInt32 compare( const char* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 compare( const char* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To2(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar1(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar1(s, max, offset, c, count);
+ }
+
+ static
+ char get_find_in_set_filter( const char* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( char* s, PRUint32 len, const char* set )
+ {
+ return StripChars1(s, len, set);
+ }
+
+ static
+ PRInt32 compress_chars( char* s, PRUint32 len, const char* set )
+ {
+ return CompressChars1(s, len, set);
+ }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<PRUnichar>
+ {
+ static
+ PRInt32 compare( const PRUnichar* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ NS_ASSERTION(!ic, "no case-insensitive compare here");
+ return Compare2To2(a, b, max);
+ }
+
+ static
+ PRInt32 compare( const PRUnichar* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare2To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const PRUnichar* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const char* set )
+ {
+ return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( PRUnichar* s, PRUint32 max, const char* set )
+ {
+ return StripChars2(s, max, set);
+ }
+
+ static
+ PRInt32 compress_chars( PRUnichar* s, PRUint32 len, const char* set )
+ {
+ return CompressChars2(s, len, set);
+ }
+ };
+
+//-----------------------------------------------------------------------------
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+ for (i=0; i<=max; ++i, ++big)
+ {
+ if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+
+ const L* iter = big + max;
+ for (i=max; iter >= big; --i, --iter)
+ {
+ if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ const CharT* end = data + dataLen;
+ for (const CharT* iter = data; iter < end; ++iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const SetCharT* charInSet = set;
+ CharT setChar = CharT(*charInSet);
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = CharT(*(++charInSet));
+ }
+ }
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const CharT* charInSet = set;
+ CharT setChar = *charInSet;
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = *(++charInSet);
+ }
+ }
+ return kNotFound;
+ }
+
+/**
+ * This is a copy of |PR_cnvtf| with a bug fixed. (The second argument
+ * of PR_dtoa is 2 rather than 1.)
+ *
+ * XXXdarin if this is the right thing, then why wasn't it fixed in NSPR?!?
+ */
+void
+Modified_cnvtf(char *buf, int bufsz, int prcsn, double fval)
+{
+ PRIntn decpt, sign, numdigits;
+ char *num, *nump;
+ char *bufp = buf;
+ char *endnum;
+
+ /* If anything fails, we store an empty string in 'buf' */
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ num = (char*)RTMemAlloc(bufsz);
+#else
+ num = (char*)malloc(bufsz);
+#endif
+ if (num == NULL) {
+ buf[0] = '\0';
+ return;
+ }
+ if (PR_dtoa(fval, 2, prcsn, &decpt, &sign, &endnum, num, bufsz)
+ == PR_FAILURE) {
+ buf[0] = '\0';
+ goto done;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ /*
+ * The NSPR code had a fancy way of checking that we weren't dealing
+ * with -0.0 or -NaN, but I'll just use < instead.
+ * XXX Should we check !isnan(fval) as well? Is it portable? We
+ * probably don't need to bother since NAN isn't portable.
+ */
+ if (sign && fval < 0.0f) {
+ *bufp++ = '-';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */
+ goto done;
+ }
+
+ if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) {
+ *bufp++ = *nump++;
+ if (numdigits != 1) {
+ *bufp++ = '.';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = 'e';
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1);
+ }
+ else if (decpt >= 0) {
+ if (decpt == 0) {
+ *bufp++ = '0';
+ }
+ else {
+ while (decpt--) {
+ if (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ else {
+ *bufp++ = '0';
+ }
+ }
+ }
+ if (*nump != '\0') {
+ *bufp++ = '.';
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = '\0';
+ }
+ else if (decpt < 0) {
+ *bufp++ = '0';
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = '\0';
+ }
+done:
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(num);
+#else
+ free(num);
+#endif
+}
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ */
+static void
+Find_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ // |count| specifies how many iterations to make from |offset|
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+ else if (PRUint32(offset) > bigLen)
+ {
+ count = 0;
+ return;
+ }
+
+ PRInt32 maxCount = bigLen - offset;
+ if (count < 0 || count > maxCount)
+ {
+ count = maxCount;
+ }
+ else
+ {
+ count += littleLen;
+ if (count > maxCount)
+ count = maxCount;
+ }
+ }
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon entry,
+ * |offset| specifies the end point from which to search backwards
+ * |count| specifies the number of iterations from |offset|
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ *
+ *
+ * EXAMPLE
+ *
+ * + -- littleLen=4 -- +
+ * : :
+ * |____|____|____|____|____|____|____|____|____|____|____|____|
+ * : :
+ * offset=5 bigLen=12
+ *
+ * if count = 4, then we expect this function to return offset = 2 and
+ * count = 7.
+ *
+ */
+static void
+RFind_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ if (littleLen > bigLen)
+ {
+ offset = 0;
+ count = 0;
+ return;
+ }
+
+ if (offset < 0)
+ offset = bigLen - littleLen;
+ if (count < 0)
+ count = offset + 1;
+
+ PRInt32 start = offset - count + 1;
+ if (start < 0)
+ start = 0;
+
+ count = offset + littleLen - start;
+ offset = start;
+ }
+
+//-----------------------------------------------------------------------------
+
+ // define nsString obsolete methods
+#include "string-template-def-unichar.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+ // define nsCString obsolete methods
+#include "string-template-def-char.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+//-----------------------------------------------------------------------------
+
+// specialized methods:
+
+PRInt32
+nsString::Find( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::Find( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return Find(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::RFind( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::RFind( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return RFind(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::FindCharInSet( const PRUnichar* aSet, PRInt32 aOffset ) const
+ {
+ if (aOffset < 0)
+ aOffset = 0;
+ else if (aOffset >= PRInt32(mLength))
+ return kNotFound;
+
+ PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+
+ /**
+ * nsTString::Compare,CompareWithConversion,etc.
+ */
+
+PRInt32
+nsCString::Compare( const char* aString, PRBool aIgnoreCase, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = char_traits::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = (mLength < strLen) ? -1 : 1;
+ }
+ return result;
+ }
+
+PRBool
+nsString::EqualsIgnoreCase( const char* aString, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = nsCharTraits<char>::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<PRUnichar>::compare(mData, aString, compareCount, PR_TRUE);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = 1; // Arbitrarily using any number != 0
+ }
+ return result == 0;
+ }
+
+ /**
+ * ToCString, ToFloat, ToInteger
+ */
+
+char*
+nsString::ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset ) const
+ {
+ // because the old implementation checked aBuf
+ if (!(aBuf && aBufLength > 0 && aOffset <= mLength))
+ return nsnull;
+
+ PRUint32 maxCount = NS_MIN(aBufLength-1, mLength - aOffset);
+
+ LossyConvertEncoding<PRUnichar, char> converter(aBuf);
+ converter.write(mData + aOffset, maxCount);
+ converter.write_terminator();
+ return aBuf;
+ }
+
+float
+nsCString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ if (mLength > 0)
+ {
+ char *conv_stopped;
+ const char *str = mData;
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters)
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+float
+nsString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ char buf[100];
+ if (mLength > 0 && mLength < sizeof(buf))
+ {
+ char *conv_stopped;
+ const char *str = ToCString(buf, sizeof(buf));
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters) or too long (sizeof(buf))
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+
+ /**
+ * nsTString::AssignWithConversion
+ */
+
+void
+nsCString::AssignWithConversion( const nsAString& aData )
+ {
+ LossyCopyUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AssignWithConversion( const nsACString& aData )
+ {
+ CopyASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendWithConversion
+ */
+
+void
+nsCString::AppendWithConversion( const nsAString& aData )
+ {
+ LossyAppendUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AppendWithConversion( const nsACString& aData )
+ {
+ AppendASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendInt
+ */
+
+void
+nsCString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+void
+nsCString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+ /**
+ * nsTString::AppendFloat
+ */
+
+void
+nsCString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ Append(buf);
+ }
+
+void
+nsString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ AppendWithConversion(buf);
+ }
+
+#endif // !MOZ_STRING_WITH_OBSOLETE_API