diff options
Diffstat (limited to 'xpcom/string/nsStringObsolete.cpp')
-rw-r--r-- | xpcom/string/nsStringObsolete.cpp | 1053 |
1 files changed, 1053 insertions, 0 deletions
diff --git a/xpcom/string/nsStringObsolete.cpp b/xpcom/string/nsStringObsolete.cpp new file mode 100644 index 000000000..bd6daacab --- /dev/null +++ b/xpcom/string/nsStringObsolete.cpp @@ -0,0 +1,1053 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#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" + +/* ***** 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! ;-) + */ + +// avoid STDC's tolower since it may do weird things with non-ASCII bytes +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 int32_t +FindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { + + if(anOffset < 0) + anOffset=0; + + if(aCount < 0) + aCount = (int32_t)aDestLength; + + if((aChar < 256) && (0 < aDestLength) && ((uint32_t)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; + + int32_t 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 int32_t +FindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { + + if(anOffset < 0) + anOffset=0; + + if(aCount < 0) + aCount = (int32_t)aDestLength; + + if((0<aDestLength) && ((uint32_t)anOffset < aDestLength)) { + + if(0<aCount) { + + const char16_t* root = aDest; + const char16_t* left = root+anOffset; + const char16_t* last = left+aCount; + const char16_t* max = root+aDestLength; + const char16_t* 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 int32_t +RFindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { + + if(anOffset < 0) + anOffset=(int32_t)aDestLength-1; + + if(aCount < 0) + aCount = int32_t(aDestLength); + + if((aChar<256) && (0 < aDestLength) && ((uint32_t)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 int32_t +RFindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { + + if(anOffset < 0) + anOffset=(int32_t)aDestLength-1; + + if(aCount < 0) + aCount = int32_t(aDestLength); + + if((0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { + + if(0 < aCount) { + + const char16_t* root = aDest; + const char16_t* rightmost = root + anOffset; + const char16_t* min = rightmost - aCount + 1; + const char16_t* 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 */ +int32_t +Compare1To1(const char* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase) { + int32_t result=0; + if(aIgnoreCase) + result=int32_t(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 */ +int32_t +Compare2To2(const char16_t* aStr1,const char16_t* aStr2,uint32_t aCount){ + int32_t result; + + if ( aStr1 && aStr2 ) + result = nsCharTraits<char16_t>::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 */ +int32_t +Compare2To1(const char16_t* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase){ + const char16_t* s1 = aStr1; + const char *s2 = aStr2; + + if (aStr1 && aStr2) { + if (aCount != 0) { + do { + + char16_t c1 = *s1++; + char16_t c2 = char16_t((unsigned char)*s2++); + + if (c1 != c2) { +#ifdef 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 int32_t +Compare1To2(const char* aStr1,const char16_t* aStr2,uint32_t aCount,bool 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 int32_t +CompressChars1(char* aString,uint32_t 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)){ + uint32_t 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 int32_t +CompressChars2(char16_t* aString,uint32_t aLength,const char* aSet) { + + char16_t* from = aString; + char16_t* end = from + aLength; + char16_t* 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)){ + uint32_t aSetLen=strlen(aSet); + + while (from < end) { + char16_t 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 - (char16_t*)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 int32_t +StripChars1(char* aString,uint32_t aLength,const char* aSet) { + + // XXX(darin): this code should defer writing until necessary. + + char* to = aString; + char* from = aString-1; + char* end = aString + aLength; + + if(aSet && aString && (0 < aLength)){ + uint32_t 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 int32_t +StripChars2(char16_t* aString,uint32_t aLength,const char* aSet) { + + // XXX(darin): this code should defer writing until necessary. + + char16_t* to = aString; + char16_t* from = aString-1; + char16_t* end = to + aLength; + + if(aSet && aString && (0 < aLength)){ + uint32_t aSetLen=strlen(aSet); + while (++from < end) { + char16_t 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 - (char16_t*)aString; +} + +/* ***** END RICKG BLOCK ***** */ + +static const char* kWhitespace="\f\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 {}; + +template <> +struct nsBufferRoutines<char> +{ + static + int32_t compare( const char* a, const char* b, uint32_t max, bool ic ) + { + return Compare1To1(a, b, max, ic); + } + + static + int32_t compare( const char* a, const char16_t* b, uint32_t max, bool ic ) + { + return Compare1To2(a, b, max, ic); + } + + static + int32_t find_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) + { + return FindChar1(s, max, offset, c, count); + } + + static + int32_t rfind_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) + { + return RFindChar1(s, max, offset, c, count); + } + + static + char get_find_in_set_filter( const char* set ) + { + return GetFindInSetFilter(set); + } + + static + int32_t strip_chars( char* s, uint32_t len, const char* set ) + { + return StripChars1(s, len, set); + } + + static + int32_t compress_chars( char* s, uint32_t len, const char* set ) + { + return CompressChars1(s, len, set); + } +}; + +template <> +struct nsBufferRoutines<char16_t> +{ + static + int32_t compare( const char16_t* a, const char16_t* b, uint32_t max, bool ic ) + { + NS_ASSERTION(!ic, "no case-insensitive compare here"); + return Compare2To2(a, b, max); + } + + static + int32_t compare( const char16_t* a, const char* b, uint32_t max, bool ic ) + { + return Compare2To1(a, b, max, ic); + } + + static + int32_t find_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) + { + return FindChar2(s, max, offset, c, count); + } + + static + int32_t rfind_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) + { + return RFindChar2(s, max, offset, c, count); + } + + static + char16_t get_find_in_set_filter( const char16_t* set ) + { + return GetFindInSetFilter(set); + } + + static + char16_t get_find_in_set_filter( const char* set ) + { + return (~char16_t(0)^~char(0)) | GetFindInSetFilter(set); + } + + static + int32_t strip_chars( char16_t* s, uint32_t max, const char* set ) + { + return StripChars2(s, max, set); + } + + static + int32_t compress_chars( char16_t* s, uint32_t len, const char* set ) + { + return CompressChars2(s, len, set); + } +}; + +//----------------------------------------------------------------------------- + +template <class L, class R> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +int32_t +FindSubstring( const L* big, uint32_t bigLen, + const R* little, uint32_t littleLen, + bool ignoreCase ) +{ + if (littleLen > bigLen) + return kNotFound; + + int32_t i, max = int32_t(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 */ +int32_t +RFindSubstring( const L* big, uint32_t bigLen, + const R* little, uint32_t littleLen, + bool ignoreCase ) +{ + if (littleLen > bigLen) + return kNotFound; + + int32_t i, max = int32_t(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 */ +int32_t +FindCharInSet( const CharT* data, uint32_t 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 */ +int32_t +RFindCharInSet( const CharT* data, uint32_t 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 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( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count ) +{ + // |count| specifies how many iterations to make from |offset| + + if (offset < 0) + { + offset = 0; + } + else if (uint32_t(offset) > bigLen) + { + count = 0; + return; + } + + int32_t 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( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count ) +{ + if (littleLen > bigLen) + { + offset = 0; + count = 0; + return; + } + + if (offset < 0) + offset = bigLen - littleLen; + if (count < 0) + count = offset + 1; + + int32_t 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: + +int32_t +nsString::Find( const nsAFlatString& aString, int32_t aOffset, int32_t aCount ) const +{ + // this method changes the meaning of aOffset and aCount: + Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + int32_t result = FindSubstring(mData + aOffset, aCount, static_cast<const char16_t*>(aString.get()), aString.Length(), false); + if (result != kNotFound) + result += aOffset; + return result; +} + +int32_t +nsString::Find( const char16_t* aString, int32_t aOffset, int32_t aCount ) const +{ + return Find(nsDependentString(aString), aOffset, aCount); +} + +int32_t +nsString::RFind( const nsAFlatString& aString, int32_t aOffset, int32_t aCount ) const +{ + // this method changes the meaning of aOffset and aCount: + RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + int32_t result = RFindSubstring(mData + aOffset, aCount, static_cast<const char16_t*>(aString.get()), aString.Length(), false); + if (result != kNotFound) + result += aOffset; + return result; +} + +int32_t +nsString::RFind( const char16_t* aString, int32_t aOffset, int32_t aCount ) const +{ + return RFind(nsDependentString(aString), aOffset, aCount); +} + +int32_t +nsString::FindCharInSet( const char16_t* aSet, int32_t aOffset ) const +{ + if (aOffset < 0) + aOffset = 0; + else if (aOffset >= int32_t(mLength)) + return kNotFound; + + int32_t result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet); + if (result != kNotFound) + result += aOffset; + return result; +} + +void +nsString::ReplaceChar( const char16_t* aSet, char16_t aNewChar ) +{ + if (!EnsureMutable()) // XXX do this lazily? + AllocFailed(mLength); + + char16_t* data = mData; + uint32_t lenRemaining = mLength; + + while (lenRemaining) + { + int32_t i = ::FindCharInSet(data, lenRemaining, aSet); + if (i == kNotFound) + break; + + data[i++] = aNewChar; + data += i; + lenRemaining -= i; + } +} + + +/** + * nsTString::Compare,CompareWithConversion,etc. + */ + +int32_t +nsCString::Compare( const char* aString, bool aIgnoreCase, int32_t aCount ) const +{ + uint32_t strLen = char_traits::length(aString); + + int32_t maxCount = int32_t(XPCOM_MIN(mLength, strLen)); + + int32_t compareCount; + if (aCount < 0 || aCount > maxCount) + compareCount = maxCount; + else + compareCount = aCount; + + int32_t result = + nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase); + + if (result == 0 && + (aCount < 0 || strLen < uint32_t(aCount) || mLength < uint32_t(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; +} + +bool +nsString::EqualsIgnoreCase( const char* aString, int32_t aCount ) const +{ + uint32_t strLen = nsCharTraits<char>::length(aString); + + int32_t maxCount = int32_t(XPCOM_MIN(mLength, strLen)); + + int32_t compareCount; + if (aCount < 0 || aCount > maxCount) + compareCount = maxCount; + else + compareCount = aCount; + + int32_t result = + nsBufferRoutines<char16_t>::compare(mData, aString, compareCount, true); + + if (result == 0 && + (aCount < 0 || strLen < uint32_t(aCount) || mLength < uint32_t(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; +} + + +/** + * nsTString::ToDouble + */ + +double +nsCString::ToDouble(nsresult* aErrorCode) const +{ + double res = 0.0; + if (mLength > 0) + { + char *conv_stopped; + const char *str = mData; + // Use PR_strtod, not strtod, since we don't want locale involved. + res = PR_strtod(str, &conv_stopped); + if (conv_stopped == str+mLength) + *aErrorCode = NS_OK; + else // Not all the string was scanned + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; + } + else + { + // The string was too short (0 characters) + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; + } + return res; +} + +double +nsString::ToDouble(nsresult* aErrorCode) const +{ + return NS_LossyConvertUTF16toASCII(*this).ToDouble(aErrorCode); +} + + +/** + * nsTString::AssignWithConversion + */ + +void +nsCString::AssignWithConversion( const nsAString& aData ) +{ + LossyCopyUTF16toASCII(aData, *this); +} + +void +nsString::AssignWithConversion( const nsACString& aData ) +{ + CopyASCIItoUTF16(aData, *this); +} + +#endif // !MOZ_STRING_WITH_OBSOLETE_API |