Bug 572417 - Release mouse capture in flash subclass after mouse events get delivered...
[mozilla-central.git] / xpcom / glue / nsStringAPI.cpp
blobc94e6020f8cd310b579dd0ca288a93db8d0bbd11
1 /* vim:set ts=2 sw=2 et cindent: */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla.
17 * The Initial Developer of the Original Code is IBM Corporation.
18 * Portions created by IBM Corporation are Copyright (C) 2003
19 * IBM Corporation. All Rights Reserved.
21 * Contributor(s):
22 * Darin Fisher <darin@meer.net>
23 * Benjamin Smedberg <benjamin@smedbergs.us>
24 * Ben Turner <mozilla@songbirdnest.com>
25 * Prasad Sunkari <prasad@medhas.org>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nscore.h"
42 #include "nsCRTGlue.h"
43 #include "prprf.h"
44 #include "nsStringAPI.h"
45 #include "nsXPCOMStrings.h"
46 #include "nsDebug.h"
48 #include <stdio.h>
50 #ifdef XP_WIN
51 #define snprintf _snprintf
52 #endif
54 // nsAString
56 PRUint32
57 nsAString::BeginReading(const char_type **begin, const char_type **end) const
59 PRUint32 len = NS_StringGetData(*this, begin);
60 if (end)
61 *end = *begin + len;
63 return len;
66 const nsAString::char_type*
67 nsAString::BeginReading() const
69 const char_type *data;
70 NS_StringGetData(*this, &data);
71 return data;
74 const nsAString::char_type*
75 nsAString::EndReading() const
77 const char_type *data;
78 PRUint32 len = NS_StringGetData(*this, &data);
79 return data + len;
82 PRUint32
83 nsAString::BeginWriting(char_type **begin, char_type **end, PRUint32 newSize)
85 PRUint32 len = NS_StringGetMutableData(*this, newSize, begin);
86 if (end)
87 *end = *begin + len;
89 return len;
92 nsAString::char_type*
93 nsAString::BeginWriting(PRUint32 aLen)
95 char_type *data;
96 NS_StringGetMutableData(*this, aLen, &data);
97 return data;
100 nsAString::char_type*
101 nsAString::EndWriting()
103 char_type *data;
104 PRUint32 len = NS_StringGetMutableData(*this, PR_UINT32_MAX, &data);
105 return data + len;
108 PRBool
109 nsAString::SetLength(PRUint32 aLen)
111 char_type *data;
112 NS_StringGetMutableData(*this, aLen, &data);
113 return data != nsnull;
116 void
117 nsAString::AssignLiteral(const char *aStr)
119 PRUint32 len = strlen(aStr);
120 PRUnichar *buf = BeginWriting(len);
121 if (!buf)
122 return;
124 for (; *aStr; ++aStr, ++buf)
125 *buf = *aStr;
128 void
129 nsAString::AppendLiteral(const char *aASCIIStr)
131 PRUint32 appendLen = strlen(aASCIIStr);
133 PRUint32 thisLen = Length();
134 PRUnichar *begin, *end;
135 BeginWriting(&begin, &end, appendLen + thisLen);
136 if (!begin)
137 return;
139 for (begin += thisLen; begin < end; ++begin, ++aASCIIStr)
140 *begin = *aASCIIStr;
143 void
144 nsAString::StripChars(const char *aSet)
146 nsString copy(*this);
148 const char_type *source, *sourceEnd;
149 copy.BeginReading(&source, &sourceEnd);
151 char_type *dest;
152 BeginWriting(&dest);
153 if (!dest)
154 return;
156 char_type *curDest = dest;
158 for (; source < sourceEnd; ++source) {
159 const char *test;
160 for (test = aSet; *test; ++test) {
161 if (*source == char_type(*test))
162 break;
165 if (!*test) {
166 // not stripped, copy this char
167 *curDest = *source;
168 ++curDest;
172 SetLength(curDest - dest);
175 void
176 nsAString::Trim(const char *aSet, PRBool aLeading, PRBool aTrailing)
178 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
180 const PRUnichar *start, *end;
181 PRUint32 cutLen;
183 if (aLeading) {
184 BeginReading(&start, &end);
185 for (cutLen = 0; start < end; ++start, ++cutLen) {
186 const char *test;
187 for (test = aSet; *test; ++test) {
188 if (*test == *start)
189 break;
191 if (!*test)
192 break;
194 if (cutLen) {
195 NS_StringCutData(*this, 0, cutLen);
198 if (aTrailing) {
199 PRUint32 len = BeginReading(&start, &end);
200 --end;
201 for (cutLen = 0; end >= start; --end, ++cutLen) {
202 const char *test;
203 for (test = aSet; *test; ++test) {
204 if (*test == *end)
205 break;
207 if (!*test)
208 break;
210 if (cutLen) {
211 NS_StringCutData(*this, len - cutLen, cutLen);
216 PRInt32
217 nsAString::DefaultComparator(const char_type *a, const char_type *b,
218 PRUint32 len)
220 for (const char_type *end = a + len; a < end; ++a, ++b) {
221 if (*a == *b)
222 continue;
224 return *a < *b ? -1 : 1;
227 return 0;
230 PRInt32
231 nsAString::Compare(const char_type *other, ComparatorFunc c) const
233 const char_type *cself;
234 PRUint32 selflen = NS_StringGetData(*this, &cself);
235 PRUint32 otherlen = NS_strlen(other);
236 PRUint32 comparelen = selflen <= otherlen ? selflen : otherlen;
238 PRInt32 result = c(cself, other, comparelen);
239 if (result == 0) {
240 if (selflen < otherlen)
241 return -1;
242 else if (selflen > otherlen)
243 return 1;
245 return result;
248 PRInt32
249 nsAString::Compare(const self_type &other, ComparatorFunc c) const
251 const char_type *cself, *cother;
252 PRUint32 selflen = NS_StringGetData(*this, &cself);
253 PRUint32 otherlen = NS_StringGetData(other, &cother);
254 PRUint32 comparelen = selflen <= otherlen ? selflen : otherlen;
256 PRInt32 result = c(cself, cother, comparelen);
257 if (result == 0) {
258 if (selflen < otherlen)
259 return -1;
260 else if (selflen > otherlen)
261 return 1;
263 return result;
266 PRBool
267 nsAString::Equals(const char_type *other, ComparatorFunc c) const
269 const char_type *cself;
270 PRUint32 selflen = NS_StringGetData(*this, &cself);
271 PRUint32 otherlen = NS_strlen(other);
273 if (selflen != otherlen)
274 return PR_FALSE;
276 return c(cself, other, selflen) == 0;
279 PRBool
280 nsAString::Equals(const self_type &other, ComparatorFunc c) const
282 const char_type *cself;
283 const char_type *cother;
284 PRUint32 selflen = NS_StringGetData(*this, &cself);
285 PRUint32 otherlen = NS_StringGetData(other, &cother);
287 if (selflen != otherlen)
288 return PR_FALSE;
290 return c(cself, cother, selflen) == 0;
293 PRBool
294 nsAString::EqualsLiteral(const char *aASCIIString) const
296 const PRUnichar *begin, *end;
297 BeginReading(&begin, &end);
299 for (; begin < end; ++begin, ++aASCIIString) {
300 if (!*aASCIIString || !NS_IsAscii(*begin) ||
301 (char) *begin != *aASCIIString) {
302 return PR_FALSE;
306 return *aASCIIString == nsnull;
309 PRBool
310 nsAString::LowerCaseEqualsLiteral(const char *aASCIIString) const
312 const PRUnichar *begin, *end;
313 BeginReading(&begin, &end);
315 for (; begin < end; ++begin, ++aASCIIString) {
316 if (!*aASCIIString || !NS_IsAscii(*begin) ||
317 NS_ToLower((char) *begin) != *aASCIIString) {
318 return PR_FALSE;
322 return *aASCIIString == nsnull;
325 PRInt32
326 nsAString::Find(const self_type& aStr, PRUint32 aOffset,
327 ComparatorFunc c) const
329 const char_type *begin, *end;
330 PRUint32 selflen = BeginReading(&begin, &end);
332 if (aOffset > selflen)
333 return -1;
335 const char_type *other;
336 PRUint32 otherlen = aStr.BeginReading(&other);
338 if (otherlen > selflen - aOffset)
339 return -1;
341 // We want to stop searching otherlen characters before the end of the string
342 end -= otherlen;
344 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
345 if (!c(cur, other, otherlen))
346 return cur - begin;
348 return -1;
351 static PRBool ns_strnmatch(const PRUnichar *aStr, const char* aSubstring,
352 PRUint32 aLen)
354 for (; aLen; ++aStr, ++aSubstring, --aLen) {
355 if (!NS_IsAscii(*aStr))
356 return PR_FALSE;
358 if ((char) *aStr != *aSubstring)
359 return PR_FALSE;
362 return PR_TRUE;
365 static PRBool ns_strnimatch(const PRUnichar *aStr, const char* aSubstring,
366 PRUint32 aLen)
368 for (; aLen; ++aStr, ++aSubstring, --aLen) {
369 if (!NS_IsAscii(*aStr))
370 return PR_FALSE;
372 if (NS_ToLower((char) *aStr) != NS_ToLower(*aSubstring))
373 return PR_FALSE;
376 return PR_TRUE;
379 PRInt32
380 nsAString::Find(const char *aStr, PRUint32 aOffset, PRBool aIgnoreCase) const
382 PRBool (*match)(const PRUnichar*, const char*, PRUint32) =
383 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
385 const char_type *begin, *end;
386 PRUint32 selflen = BeginReading(&begin, &end);
388 if (aOffset > selflen)
389 return -1;
391 PRUint32 otherlen = strlen(aStr);
393 if (otherlen > selflen - aOffset)
394 return -1;
396 // We want to stop searching otherlen characters before the end of the string
397 end -= otherlen;
399 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
400 if (match(cur, aStr, otherlen)) {
401 return cur - begin;
404 return -1;
407 PRInt32
408 nsAString::RFind(const self_type& aStr, PRInt32 aOffset, ComparatorFunc c) const
410 const char_type *begin, *end;
411 PRUint32 selflen = BeginReading(&begin, &end);
413 const char_type *other;
414 PRUint32 otherlen = aStr.BeginReading(&other);
416 if (selflen < otherlen)
417 return -1;
419 if (aOffset < 0 || PRUint32(aOffset) > (selflen - otherlen))
420 end -= otherlen;
421 else
422 end = begin + aOffset;
424 for (const char_type *cur = end; cur >= begin; --cur) {
425 if (!c(cur, other, otherlen))
426 return cur - begin;
428 return -1;
431 PRInt32
432 nsAString::RFind(const char *aStr, PRInt32 aOffset, PRBool aIgnoreCase) const
434 PRBool (*match)(const PRUnichar*, const char*, PRUint32) =
435 aIgnoreCase ? ns_strnimatch : ns_strnmatch;
437 const char_type *begin, *end;
438 PRUint32 selflen = BeginReading(&begin, &end);
439 PRUint32 otherlen = strlen(aStr);
441 if (selflen < otherlen)
442 return -1;
444 if (aOffset < 0 || PRUint32(aOffset) > (selflen - otherlen))
445 end -= otherlen;
446 else
447 end = begin + aOffset;
449 for (const char_type *cur = end; cur >= begin; --cur) {
450 if (match(cur, aStr, otherlen)) {
451 return cur - begin;
454 return -1;
457 PRInt32
458 nsAString::FindChar(char_type aChar, PRUint32 aOffset) const
460 const char_type *start, *end;
461 PRUint32 len = BeginReading(&start, &end);
462 if (aOffset > len)
463 return -1;
465 const char_type *cur;
467 for (cur = start + aOffset; cur < end; ++cur) {
468 if (*cur == aChar)
469 return cur - start;
472 return -1;
475 PRInt32
476 nsAString::RFindChar(char_type aChar) const
478 const PRUnichar *start, *end;
479 BeginReading(&start, &end);
481 do {
482 --end;
484 if (*end == aChar)
485 return end - start;
487 } while (end >= start);
489 return -1;
492 void
493 nsAString::AppendInt(int aInt, PRInt32 aRadix)
495 const char *fmt;
496 switch (aRadix) {
497 case 8:
498 fmt = "%o";
499 break;
501 case 10:
502 fmt = "%d";
503 break;
505 case 16:
506 fmt = "%x";
507 break;
509 default:
510 NS_ERROR("Unrecognized radix");
511 fmt = "";
514 char buf[20];
515 int len = snprintf(buf, sizeof(buf), fmt, aInt);
516 buf[sizeof(buf) - 1] = '\0';
518 Append(NS_ConvertASCIItoUTF16(buf, len));
521 // Strings
523 #ifndef XPCOM_GLUE_AVOID_NSPR
524 PRInt32
525 nsAString::ToInteger(nsresult *aErrorCode, PRUint32 aRadix) const
527 NS_ConvertUTF16toUTF8 narrow(*this);
529 const char *fmt;
530 switch (aRadix) {
531 case 10:
532 fmt = "%i";
533 break;
535 case 16:
536 fmt = "%x";
537 break;
539 default:
540 NS_ERROR("Unrecognized radix!");
541 *aErrorCode = NS_ERROR_INVALID_ARG;
542 return 0;
545 PRInt32 result = 0;
546 if (PR_sscanf(narrow.get(), fmt, &result) == 1)
547 *aErrorCode = NS_OK;
548 else
549 *aErrorCode = NS_ERROR_FAILURE;
551 return result;
553 #endif // XPCOM_GLUE_AVOID_NSPR
555 // nsACString
557 PRUint32
558 nsACString::BeginReading(const char_type **begin, const char_type **end) const
560 PRUint32 len = NS_CStringGetData(*this, begin);
561 if (end)
562 *end = *begin + len;
564 return len;
567 const nsACString::char_type*
568 nsACString::BeginReading() const
570 const char_type *data;
571 NS_CStringGetData(*this, &data);
572 return data;
575 const nsACString::char_type*
576 nsACString::EndReading() const
578 const char_type *data;
579 PRUint32 len = NS_CStringGetData(*this, &data);
580 return data + len;
583 PRUint32
584 nsACString::BeginWriting(char_type **begin, char_type **end, PRUint32 newSize)
586 PRUint32 len = NS_CStringGetMutableData(*this, newSize, begin);
587 if (end)
588 *end = *begin + len;
590 return len;
593 nsACString::char_type*
594 nsACString::BeginWriting(PRUint32 aLen)
596 char_type *data;
597 NS_CStringGetMutableData(*this, aLen, &data);
598 return data;
601 nsACString::char_type*
602 nsACString::EndWriting()
604 char_type *data;
605 PRUint32 len = NS_CStringGetMutableData(*this, PR_UINT32_MAX, &data);
606 return data + len;
609 PRBool
610 nsACString::SetLength(PRUint32 aLen)
612 char_type *data;
613 NS_CStringGetMutableData(*this, aLen, &data);
614 return data != nsnull;
617 void
618 nsACString::StripChars(const char *aSet)
620 nsCString copy(*this);
622 const char_type *source, *sourceEnd;
623 copy.BeginReading(&source, &sourceEnd);
625 char_type *dest;
626 BeginWriting(&dest);
627 if (!dest)
628 return;
630 char_type *curDest = dest;
632 for (; source < sourceEnd; ++source) {
633 const char *test;
634 for (test = aSet; *test; ++test) {
635 if (*source == char_type(*test))
636 break;
639 if (!*test) {
640 // not stripped, copy this char
641 *curDest = *source;
642 ++curDest;
646 SetLength(curDest - dest);
649 void
650 nsACString::Trim(const char *aSet, PRBool aLeading, PRBool aTrailing)
652 NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
654 const char *start, *end;
655 PRUint32 cutLen;
657 if (aLeading) {
658 BeginReading(&start, &end);
659 for (cutLen = 0; start < end; ++start, ++cutLen) {
660 const char *test;
661 for (test = aSet; *test; ++test) {
662 if (*test == *start)
663 break;
665 if (!*test)
666 break;
668 if (cutLen) {
669 NS_CStringCutData(*this, 0, cutLen);
672 if (aTrailing) {
673 PRUint32 len = BeginReading(&start, &end);
674 --end;
675 for (cutLen = 0; end >= start; --end, ++cutLen) {
676 const char *test;
677 for (test = aSet; *test; ++test) {
678 if (*test == *end)
679 break;
681 if (!*test)
682 break;
684 if (cutLen) {
685 NS_CStringCutData(*this, len - cutLen, cutLen);
690 PRInt32
691 nsACString::DefaultComparator(const char_type *a, const char_type *b,
692 PRUint32 len)
694 return memcmp(a, b, len);
697 PRInt32
698 nsACString::Compare(const char_type *other, ComparatorFunc c) const
700 const char_type *cself;
701 PRUint32 selflen = NS_CStringGetData(*this, &cself);
702 PRUint32 otherlen = strlen(other);
703 PRUint32 comparelen = selflen <= otherlen ? selflen : otherlen;
705 PRInt32 result = c(cself, other, comparelen);
706 if (result == 0) {
707 if (selflen < otherlen)
708 return -1;
709 else if (selflen > otherlen)
710 return 1;
712 return result;
715 PRInt32
716 nsACString::Compare(const self_type &other, ComparatorFunc c) const
718 const char_type *cself, *cother;
719 PRUint32 selflen = NS_CStringGetData(*this, &cself);
720 PRUint32 otherlen = NS_CStringGetData(other, &cother);
721 PRUint32 comparelen = selflen <= otherlen ? selflen : otherlen;
723 PRInt32 result = c(cself, cother, comparelen);
724 if (result == 0) {
725 if (selflen < otherlen)
726 return -1;
727 else if (selflen > otherlen)
728 return 1;
730 return result;
733 PRBool
734 nsACString::Equals(const char_type *other, ComparatorFunc c) const
736 const char_type *cself;
737 PRUint32 selflen = NS_CStringGetData(*this, &cself);
738 PRUint32 otherlen = strlen(other);
740 if (selflen != otherlen)
741 return PR_FALSE;
743 return c(cself, other, selflen) == 0;
746 PRBool
747 nsACString::Equals(const self_type &other, ComparatorFunc c) const
749 const char_type *cself;
750 const char_type *cother;
751 PRUint32 selflen = NS_CStringGetData(*this, &cself);
752 PRUint32 otherlen = NS_CStringGetData(other, &cother);
754 if (selflen != otherlen)
755 return PR_FALSE;
757 return c(cself, cother, selflen) == 0;
760 PRInt32
761 nsACString::Find(const self_type& aStr, PRUint32 aOffset,
762 ComparatorFunc c) const
764 const char_type *begin, *end;
765 PRUint32 selflen = BeginReading(&begin, &end);
767 if (aOffset > selflen)
768 return -1;
770 const char_type *other;
771 PRUint32 otherlen = aStr.BeginReading(&other);
773 if (otherlen > selflen - aOffset)
774 return -1;
776 // We want to stop searching otherlen characters before the end of the string
777 end -= otherlen;
779 for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
780 if (!c(cur, other, otherlen))
781 return cur - begin;
783 return -1;
786 PRInt32
787 nsACString::Find(const char_type *aStr, ComparatorFunc c) const
789 return Find(aStr, strlen(aStr), c);
792 PRInt32
793 nsACString::Find(const char_type *aStr, PRUint32 aLen, ComparatorFunc c) const
795 const char_type *begin, *end;
796 PRUint32 selflen = BeginReading(&begin, &end);
798 if (aLen == 0) {
799 NS_WARNING("Searching for zero-length string.");
800 return -1;
803 if (aLen > selflen)
804 return -1;
806 // We want to stop searching otherlen characters before the end of the string
807 end -= aLen;
809 for (const char_type *cur = begin; cur <= end; ++cur) {
810 if (!c(cur, aStr, aLen))
811 return cur - begin;
813 return -1;
816 PRInt32
817 nsACString::RFind(const self_type& aStr, PRInt32 aOffset, ComparatorFunc c) const
819 const char_type *begin, *end;
820 PRUint32 selflen = BeginReading(&begin, &end);
822 const char_type *other;
823 PRUint32 otherlen = aStr.BeginReading(&other);
825 if (selflen < otherlen)
826 return -1;
828 if (aOffset < 0 || PRUint32(aOffset) > (selflen - otherlen))
829 end -= otherlen;
830 else
831 end = begin + aOffset;
833 for (const char_type *cur = end; cur >= begin; --cur) {
834 if (!c(cur, other, otherlen))
835 return cur - begin;
837 return -1;
840 PRInt32
841 nsACString::RFind(const char_type *aStr, ComparatorFunc c) const
843 return RFind(aStr, strlen(aStr), c);
846 PRInt32
847 nsACString::RFind(const char_type *aStr, PRInt32 aLen, ComparatorFunc c) const
849 const char_type *begin, *end;
850 PRUint32 selflen = BeginReading(&begin, &end);
852 if (aLen <= 0) {
853 NS_WARNING("Searching for zero-length string.");
854 return -1;
857 if (PRUint32(aLen) > selflen)
858 return -1;
860 // We want to start searching otherlen characters before the end of the string
861 end -= aLen;
863 for (const char_type *cur = end; cur >= begin; --cur) {
864 if (!c(cur, aStr, aLen))
865 return cur - begin;
867 return -1;
870 PRInt32
871 nsACString::FindChar(char_type aChar, PRUint32 aOffset) const
873 const char_type *start, *end;
874 PRUint32 len = BeginReading(&start, &end);
875 if (aOffset > len)
876 return -1;
878 const char_type *cur;
880 for (cur = start + aOffset; cur < end; ++cur) {
881 if (*cur == aChar)
882 return cur - start;
885 return -1;
888 PRInt32
889 nsACString::RFindChar(char_type aChar) const
891 const char *start, *end;
892 BeginReading(&start, &end);
894 for (; end >= start; --end) {
895 if (*end == aChar)
896 return end - start;
899 return -1;
902 void
903 nsACString::AppendInt(int aInt, PRInt32 aRadix)
905 const char *fmt;
906 switch (aRadix) {
907 case 8:
908 fmt = "%o";
909 break;
911 case 10:
912 fmt = "%d";
913 break;
915 case 16:
916 fmt = "%x";
917 break;
919 default:
920 NS_ERROR("Unrecognized radix");
921 fmt = "";
924 char buf[20];
925 int len = snprintf(buf, sizeof(buf), fmt, aInt);
926 buf[sizeof(buf) - 1] = '\0';
928 Append(buf, len);
931 #ifndef XPCOM_GLUE_AVOID_NSPR
932 PRInt32
933 nsACString::ToInteger(nsresult *aErrorCode, PRUint32 aRadix) const
935 const char *fmt;
936 switch (aRadix) {
937 case 10:
938 fmt = "%i";
939 break;
941 case 16:
942 fmt = "%x";
943 break;
945 default:
946 NS_ERROR("Unrecognized radix!");
947 *aErrorCode = NS_ERROR_INVALID_ARG;
948 return 0;
951 PRInt32 result = 0;
952 if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
953 *aErrorCode = NS_OK;
954 else
955 *aErrorCode = NS_ERROR_FAILURE;
957 return result;
959 #endif // XPCOM_GLUE_AVOID_NSPR
961 // Substrings
963 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
964 PRUint32 aStartPos)
966 const PRUnichar* data;
967 PRUint32 len = NS_StringGetData(aStr, &data);
969 if (aStartPos > len)
970 aStartPos = len;
972 NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos,
973 NS_STRING_CONTAINER_INIT_DEPEND |
974 NS_STRING_CONTAINER_INIT_SUBSTRING);
977 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
978 PRUint32 aStartPos,
979 PRUint32 aLength)
981 const PRUnichar* data;
982 PRUint32 len = NS_StringGetData(aStr, &data);
984 if (aStartPos > len)
985 aStartPos = len;
987 if (aStartPos + aLength > len)
988 aLength = len - aStartPos;
990 NS_StringContainerInit2(*this, data + aStartPos, aLength,
991 NS_STRING_CONTAINER_INIT_DEPEND |
992 NS_STRING_CONTAINER_INIT_SUBSTRING);
995 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
996 PRUint32 aStartPos)
998 const char* data;
999 PRUint32 len = NS_CStringGetData(aStr, &data);
1001 if (aStartPos > len)
1002 aStartPos = len;
1004 NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos,
1005 NS_CSTRING_CONTAINER_INIT_DEPEND |
1006 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
1009 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
1010 PRUint32 aStartPos,
1011 PRUint32 aLength)
1013 const char* data;
1014 PRUint32 len = NS_CStringGetData(aStr, &data);
1016 if (aStartPos > len)
1017 aStartPos = len;
1019 if (aStartPos + aLength > len)
1020 aLength = len - aStartPos;
1022 NS_CStringContainerInit2(*this, data + aStartPos, aLength,
1023 NS_CSTRING_CONTAINER_INIT_DEPEND |
1024 NS_CSTRING_CONTAINER_INIT_SUBSTRING);
1027 // Utils
1029 char*
1030 ToNewUTF8String(const nsAString& aSource)
1032 nsCString temp;
1033 CopyUTF16toUTF8(aSource, temp);
1034 return NS_CStringCloneData(temp);
1037 void
1038 CompressWhitespace(nsAString& aString)
1040 PRUnichar *start;
1041 PRUint32 len = NS_StringGetMutableData(aString, PR_UINT32_MAX, &start);
1042 PRUnichar *end = start + len;
1043 PRUnichar *from = start, *to = start;
1045 // Skip any leading whitespace
1046 while (from < end && NS_IsAsciiWhitespace(*from))
1047 from++;
1049 while (from < end) {
1050 PRUnichar theChar = *from++;
1052 if (NS_IsAsciiWhitespace(theChar)) {
1053 // We found a whitespace char, so skip over any more
1054 while (from < end && NS_IsAsciiWhitespace(*from))
1055 from++;
1057 // Turn all whitespace into spaces
1058 theChar = ' ';
1061 *to++ = theChar;
1064 // Drop any trailing space
1065 if (to > start && to[-1] == ' ')
1066 to--;
1068 // Re-terminate the string
1069 *to = '\0';
1071 // Set the new length
1072 aString.SetLength(to - start);
1075 PRUint32
1076 ToLowerCase(nsACString& aStr)
1078 char *begin, *end;
1079 PRUint32 len = aStr.BeginWriting(&begin, &end);
1081 for (; begin < end; ++begin) {
1082 *begin = NS_ToLower(*begin);
1085 return len;
1088 PRUint32
1089 ToUpperCase(nsACString& aStr)
1091 char *begin, *end;
1092 PRUint32 len = aStr.BeginWriting(&begin, &end);
1094 for (; begin < end; ++begin) {
1095 *begin = NS_ToUpper(*begin);
1098 return len;
1101 PRUint32
1102 ToLowerCase(const nsACString& aSrc, nsACString& aDest)
1104 const char *begin, *end;
1105 PRUint32 len = aSrc.BeginReading(&begin, &end);
1107 char *dest;
1108 NS_CStringGetMutableData(aDest, len, &dest);
1110 for (; begin < end; ++begin, ++dest) {
1111 *dest = NS_ToLower(*begin);
1114 return len;
1117 PRUint32
1118 ToUpperCase(const nsACString& aSrc, nsACString& aDest)
1120 const char *begin, *end;
1121 PRUint32 len = aSrc.BeginReading(&begin, &end);
1123 char *dest;
1124 NS_CStringGetMutableData(aDest, len, &dest);
1126 for (; begin < end; ++begin, ++dest) {
1127 *dest = NS_ToUpper(*begin);
1130 return len;
1133 PRInt32
1134 CaseInsensitiveCompare(const char *a, const char *b,
1135 PRUint32 len)
1137 for (const char *aend = a + len; a < aend; ++a, ++b) {
1138 char la = NS_ToLower(*a);
1139 char lb = NS_ToLower(*b);
1141 if (la == lb)
1142 continue;
1144 return la < lb ? -1 : 1;
1147 return 0;
1150 PRBool
1151 ParseString(const nsACString& aSource, char aDelimiter,
1152 nsTArray<nsCString>& aArray)
1154 PRInt32 start = 0;
1155 PRInt32 end = aSource.Length();
1157 PRUint32 oldLength = aArray.Length();
1159 for (;;) {
1160 PRInt32 delimiter = aSource.FindChar(aDelimiter, start);
1161 if (delimiter < 0) {
1162 delimiter = end;
1165 if (delimiter != start) {
1166 if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) {
1167 aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
1168 return PR_FALSE;
1172 if (delimiter == end)
1173 break;
1174 start = ++delimiter;
1175 if (start == end)
1176 break;
1179 return PR_TRUE;