mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
7f8ba9c1d7
- Bug 1236786 - [WebGL2] pass getVertexAttrib in gl-object-get-calls.html, r=jgilbert (60a2c91a38)
- Bug 1233046 - Fix OES_texture_float on OSX. - r=jrmuizel (4bc0059f5f)
- Bug 1233557 - Allow RGB8 to be renderable again for web-compat. - r=jrmuizel (4c13bfd8e8)
- Bug 1233549. Disallow ES3 compressed texture formats. r=jgilbert (1073033161)
- Bug 1241702 - Allow unsized DEPTH_STENCIL for RBs in WebGL 2. - r=kamidphish (87d17d2cf9)
- Bug 1239126. Handle gl_InstanceID attribute with no location. r=jgilbert (4894997e98)
- Bug 1236782 - [WebGL2] pass getProgramParameter in gl-object-get-calls.html; r=jgilbert (2136fcce48)
- Bug 1232462. Only ask for a higher version of GLSL when using WebGL2. r=jgilbert (0317be4eb4)
- Bug 1242330 - "Four extensions were promoted to core in WebGL 2 and should no longer be available as extensions." r=jgilbert r=jmuizelaar (6df020b8d4)
- Bug 1233626 - Default MaxDrawingBuffers to 1 unless ext/webgl2. - r=jrmuizel (a7580d661c)
- Bug 1231657. Don't allow linking different versions shaders. r=jgilbert (e610f98066)
- Bug 1241777 - TexCompareFunc should be stored in ascending order. r=jgilbert (b6151a0076)
- Bug 1228885 - Implement WebGLTexture::MemoryUsage. - r=kamidphish (ea06815414)
- Bug 1239259 - Fix WebGL2 generateMipmap checking. r=jgilbert (39f587c421)
- Bug 1242347 - Allow unsized internal format when generate mipmap. r=jgilbert (b203a8898c)
- Bug 1232502. Use the correct internalFormat when calling CopyTexImage2D. r=jgilbert (eeaef3215e)
- Bug 1243663 - Max uniform and attribute location lengths in WebGL2 should be 1024. r=jgilbert (c4ec6de507)
- Bug 1239488 - Add int/uint to vertex attrib data type. r=jgilbert (11b4968025)
- Bug 1184242 - Remove aTabParent != sActiveTabParent warning from IMEStateManager::SetInputContextForChildProcess. r=masayuki (0fcda10e15)
- Bug 1178652 - Send NOTIFY_IME_OF_COMPOSITION_UPDATE to parent process correctly. r=masayuki (bce28e2c91)
- Bug 1107782 - Only accept certain mouse, gamepad events as user-active. r=smaug (00542c80b9)
- Bug 1247850 - Shrink NameTableKey in nsStaticCaseInsensitiveNameTable. r=froydnj,erahm. (ce3cb3edfb)
- Bug 1247359 - micro-optimize the common case of String{Begins,End}With; r=erahm (333e042b31)
- Bug 1239125. Add operator!=(char_type*) to nsTSubstring. r=froydnj (0cc047a9a1)
- Bug 1213862 - Align nsString whitespace handling with web specs; r=froydnj (db5b11ca52)
- Bug 1141884 - Trigger compositor smooth scrolling to snap points when APZ is enabled. r=mstange,kip (593af59f2a)
- Bug 1244582: Add back in a null check that was accidentally removed. r=smaug (76bff1b01f)
- Bug 1234176 - Introduce and use the WriteSysFile() helper function. r=dhylands (22a46fbe8b)
- missing bit of Bug 1198124 - Enable -Wshadow (f84535a7a2)
- Bug 1249171 - Simplify nsCOMArray::SizeOfExcludingThis(). r=erahm. (57efdce1c6)
- Bug 1156416 - Validate camera parameters supplied by the application. r=mikeh (f8b4b84ccf)
- Bug 1186808 - Replace nsBaseHashtable::EnumerateRead() calls in dom/camera/ with iterators. r=mikeh. (7b1db5f6a1)
- Bug 1158378 - Fix how a failed set configuration call would try to shutdown the camera after release. (9d5e323bca)
- Bug 1171374 - Permit software video codecs with the emulated camera. r=sotaro (c1ae26ea0d)
- Bug 1234458 P1 Allow the CacheChild to be "locked" into memory so it will delay destruction. r=ehsan a=ritu (9e46185779)
- Bug 1234458 P2 Lock the CacheChild actor while Cache DOM methods are running. r=ehsan a=ritu (038342a6e2)
- Bug 1244764 P1 Make Cache .add()/.addAll() fail if a Response.ok() is false. r=ehsan (ae26ca9ef1)
- Bug 1172562 - Clear QuotaManager storage when uninstalling an app. Test. r=bkelly (b07311a3b7)
- Bug 1172629 - Use the caches global property from an iframe loaded after setting the pref in order to make the tests pass with the pref disabled; r=bkelly a=RyanVM (e7c05d8b79)
- Bug 1244764 P2 Make dom/cache mochitests pass with new add()/addAll() behavior. r=ehsan (e1f667c1b4)
- Bug 1244764 P3 Make service worker tests pass with new Cache add()/addAll() behavior. r=ehsan (1518ae5225)
- Bug 1003860 - Simplify storage setup tasks in storage inspector tests. r=mratcliffe (249a8bdb2b)
- Bug 1003860 - Service worker cache for storage actor. r=mratcliffe (5c3d1ecd0c)
- Bug 1244764 P5 Fix devtools test to work with new Cache add()/addAll() behavior. r=ehsan (bf85405de8)
- Bug 1232901 - Use channel.asyncOpen2 within dom/browser-element/BrowserElementParent.js (r=sicking,aus) (2a228ed551)
- Bug 1180330 - http auth prompt shown when opening browser if prompt canceled/dismissed earlier. r=fabrice (ba3666f4bd)
- Bug 1234118 - Delete code for supporting 'do-command' and 'copypaste-docommand'. r=mtseng, r=smaug (b1b575d3c5)
- Bug 1238883 - [TV Browser] It shows "The page cannot be displayed" when user browse some webpages. r=roc (e6d7739dd6)
- Bug 1238440 - FileReader should throw an error when the blob changed size when reading, r=khuey (b006adba10)
- Bug 1230422 - FileReader should handle nested ReadAs*() calls. r=khuey (5a3ff84a31)
- Bug 1225202, part 3 - Create files in test_fileapi_slice.html using SpecialPowers.createFiles. r=baku (1137975548)
- Bug 1241171 - FormData should not force 'blob' as filename, r=smaug (748055f751)
- Bug 1246375 - Restore the previous spec version of FormData, r=smaug (3586af2b88)
- Bug 1237183 - Modify implementation of reading preference. r=seanlin (a132bc7246)
- Bug 801545 - Remove DocumentType.internalSubset, r=bz (ea30c9b5ee)
- Bug 1226440 - Expose a method to get a node's immediate dominator; r=bz,sfink (f77ae44037)
- Bug 825318 - Implement adoptDownload for mozDownloadManager, r=aus, r=sicking (e98cb05210)
- Bug 1237370 - Always log the reason for remote AppRep lookup failures. r=gcp (2c804e68fc)
- Bug 1167493 - Application Reputation: disable remote lookup of zip files on Mac/Linux, r=gcp (517459e064)
- Bug 1195519 - Use channel->ascynOpen2 toolkit/components/downloads/ApplicationReputation.cpp (r=sicking) (2856e5213a)
- Bug 1237856 - Add prefs to honor/ignore Application Reputation verdicts. r=gcp (54ee06264f)
- Bug 1243643 - Deprecate unsafe CPOW usage in contentAreaUtils' saveImage. r=jld (6ae790f1ef)
- Bug 1229224: Add an eslint plugin for importing all browser.js globals for browser-chrome tests. r=miker (9df52a7f3b)
- Bug 1245916: Add additional browser window scripts to eslint globals. r=felipe (92d316ca5e)
- Bug 1246244 - Allow non-CPOW documents to pass through saveImageURL properly. r=jaws,Margaret (c8d4ca241d)
- some missing bits after world fix (c0439eebb0)
- add some missing stuff (ddbd47dc03)
- bissing bit of 1229519 (4e255c3dae)
- Bug 1199662 - Crash ping environment block is broken when any string field contains a quotation mark. Unescape INI fields properly using the library that already exists for the purpose. r=ted (874a999edc)
- Bug 1216150 - Turn on the experimental Intl.DateTimeFormat.prototype.formatToParts in b2g certified apps. r=fabrice (40eeb1a4d4)
- Bug 1216150 - Mini-bustage fix for something I think I unintentionally qref'd into the final patch. r=bustage in a CLOSED TREE (36d9b21a67)
- Bug 1141311 - Add async mode support to GonkNativeWindow on Lollipop Gonk r=pchang (39d9d56326)
- Bug 1146671 - Ensure camera not already released when performing operations. r=dhylands (71b59caa1f)
- Bug 1248737. Improve documentation for WorkerRunnable and associated classes. r=khuey (4ff57790c5)
- Bug 1235629 - Remove dead code in WorkerFeature.h, r=smaug (75a51fcf03)
- Bug 1212333 - WorkerDebuggerManager should live on the main thread;r=khuey (11fdfbbae6)
- Bug 1226443 P3 Re-enable service worker update wpt tests. r=ehsan (605dac5f9e)
- Bug 1226443 P4 Cleanup ServiceWorkerScriptCache objects when initialization fails. r=ehsan (43de3429a2)
- Bug 1234127: Change |BluetoothAdapter.pairingReqs| as a nullable object; r=btian, r=mrbkap (45d2038f6a)
- Bug 1188487 - BrowserElement webidl changes for muting and setting volume. r=ehsan (21bea70a07)
- Bug 1238210 - Correct the Promise return types on two Clients methods; r=baku (fa41b25df0)
- Bug 1246784 - Expose Console to the WorkerDebuggerGlobalScope - part 2, r=khuey (0da9ce8ff6)
- Bug 1228702. Don't expose the 'location' property of Exception/DOMException on workers. r=bholley (0fe86ea586)
- Bug 1223825 - Change Directory.path to include the directory's name. r=baku (0cdae4c2f0)
- Bug 1238225 - Mark ExtendableMessageEvent.ports as SameObject; r=baku (45b9a9746f)
- Bug 1236933 - Return null from FetchEvent.clientId for non-subresource network requests; r=bkelly (4a9c4b40cb)
- Bug 1238213 - Make FetchEvent.request non-nullable; r=baku (751082c8ba)
- Bug 1193125 - Avoid corrupting image data in test_fetch_event.html. r=bkelly (9f6bff232f)
- Bug 1201664 - Avoid using Request's constructor when creating FetchEvent.request; r=bkelly (7a3401e345)
- Bug 1175944 - Packaged app's (app://) JS files are not loaded and do not trigger "onfetch" handler. r=jdm (62df139153)
- Bug 1233644 - use pattern matching when listening clear-origin-data. r=baku (ea2594f50e)
- Bug 1237363 - Part 1: Unregister all service workers registered in mochitests at the end of the test; r=jdm (5be97e5bb0)
- Bug 1237363 - Part 2: Fail mochitests which register a service worker without unregistering it; r=jdm (c4160ffd5f)
- Bug 1237363 - Part 3: Add a test for a mochitest finishing without unregistering its service worker; r=jdm (911d37291b)
- Bug 1174078 - Calling "fetch" inside Service Worker's "onfetch" handler in b2g causes "onfetch" again that leads to an infinite loop. Test. r=nsm (208451f346)
- Bug 1197379 - Remove support for intercepting app:// URIs using service workers; r=jdm (3cbdd725f1)
- Bug 1179399 - Part 1: Relax the ShouldIntercept checks when overriding JAR channel info; r=jdm (850bb2bdb8)
- Bug 1238213 follow-up: Mark the FetchEventInit dictionary argument to FetchEvent's constructor optional too; r=bzbarsky (356cbe6db7)
- Bug 1232732 - modify NS_WARNING in MOZ_WIN_MEM_TRY_CATCH; r=aklotz (e2be4d6919)
- Bug 1247658 - Expose a method to JS for find the shortest retaining paths of some nodes in a heap snapshot; r=bz r=jimb (2c82198808)
- Bug 1188115: Expose IDBCursorWithValue in workers. r=baku (e1c40aeb6e)
- Bug 1162680 - Notify Keyboard.jsm to send blur event when the message manager is closed first. r=timdream (53727ab300)
- Bug 1192986 Also mark Cache/CacheStorage as release interfaces on workers. r=ehsan a=bustage (25cf83c154)
- Bug 1159742. Get rid of the pref annotation from test_interfaces, since it basically corresponds to disabling the test. r=jst (c229e3f881)
- Bug 1203160 - Part 2: Fix the interfaces tests to allow SW interfaces for non-release Fennec; r=baku (072840db1f)
- Bug 1197700 - Correct mistakes in InputMethod.webidl. r=kanru, r=janjongboom, sr=smaug (4edb6f201f)
- Bug 1206970 - Stop expecting AnimationPlaybackEvent to be exposed on release branches, where it's disabled by pref, r=smaug (30ae2b13db)
- Bug 1177276 - Pref on canvas.captureStream by default. r=smaug,mt (0cfe0f72f2)
- Bug 1215147 - Enable VR API's on FF for Android by default. r=snorp, r=vlad, r=bz (5ff3725318)
- Bug 1218482 - Enable WebVR By Default,r=bz (f26111ed82)
- Bug 1159755. Stop forcing the media.eme.apiVisible preference to be true in our test harness. r=cpearce (09f7887917)
- Bug 1149312 - Obtain test coverage for the file-backed case of MediaRecorder. r=roc (bd2e7e40f0)
- Bug 1154559 - Remove flaky timeouts from manifest.js and register SimpleTest.registerCleanupFunction() to report unfinished tests. r=cpearce. (eb68db0fb2)
- Bug 1154564 - Add the ability to notify timeouts to MediaTestManager and remove flaky timeouts from test_playback.html. r=cpearce. (c89b4e58d9)
- Bug 1135170 - Fix up racey test_seek-1.html. rpending=mattwoodrow (b3a7d0dcd6)
- Bug 902686 - Change manifest.js to use SpecialPowers.pushPrefEnv. r=edwin (636b0edc1a)
- Bug 1183502 - give androidVersion a correct value in manifest.js. r=sotaro. (933e9ea712)
- Bug 1235588 - add null check to SimpleTest. r=bechen. (958ede68de)
- misspatch (c8922447ff)
- Bug 1151740 - pass the callback object as-is to SpecialPowers.exactGC(). r=edwin (99ca873bce)
- Bug 1197682 - InputMethodManager#setSupportsSwitchingTypes, r=janjongboom, sr=smaug (e7eb54e491)
- Bug 1201407 - Add input-manage-only events for InputMethod API. r=janjongboom, sr=smaug (776d064bd1)
- Bug 1234459 - Expose full text in the input box to InputMethod API, r=masayuki, sr=smaug (4fa0554356)
- Bug 1198163 - Workaround Mochitest app and assign frame proper permissions, r=kanru (c3bcf8ecc1)
- Bug 990250 - Fold nsIStyleSheet into CSSStyleSheet. r=dbaron (23579cb300)
1054 lines
28 KiB
C++
1054 lines
28 KiB
C++
/* -*- 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
|